Не удается найти wchar_t, который присутствует в std :: wstring - PullRequest
0 голосов
/ 27 июня 2018

Я играл с std::wstring и std::wfstream, когда столкнулся со странным поведением. А именно, похоже, что std::basic_string<wchar_t>::find не может найти определенные символы. Рассмотрим следующий код:

int main()
{
    std::wifstream input("input.txt");
    std::wofstream output("output.txt");

    if(!(input && output)){
        std::cerr << "file(s) not opened";
        return -1;
    }

    std::wstring buf;
    std::getline(input, buf);

    output << buf;

    std::cout << buf.find(L'ć');
}

Здесь я просто читаю первую строку файла input и записываю ее в файл output. Перед запуском программы содержимое первого файла aąbcćd, а выходной файл пуст. После выполнения кода входной файл успешно копируется в выходной файл.

Что меня удивляет, так это то, что я попытался найти письмо ć в buf и столкнулся с упомянутым странным поведением. После выполнения программы я подтвердил, что выходной файл содержит ровно aąbcćd, который, очевидно, содержит упомянутый символ ć.

Однако строка std::cout << buf.find(L'ć') не работает должным образом. Я не ожидал получить вывод 4, учитывая расположение памяти std::wstring, но я также определенно не ожидал получить std::string::npos. Стоит отметить, что с помощью этого метода можно найти обычные символы ASCII.

Подводя итог, упомянутый код правильно копирует первую строку входного файла в выходной файл, но ему не удается найти символ в строке (возвращающий npos), который отвечает за хранение данных, которые должны быть скопированы. Почему это так? Что вызывает сбой find здесь

Примечание: оба файла имеют кодировку UTF-8 в Windows.

1 Ответ

0 голосов
/ 27 июня 2018

К сожалению wchar_t - это не UTF-8, его UTF-16 (в Windows) и никакого волшебного преобразования не происходит при чтении файла UTF-8. Если вы отладите свою программу, вы увидите поврежденные символы в переменной buf.

Вам либо нужно прочитать вашу строку как std::string, затем преобразовать из UTF-8 в whar_t или работать в UTF-8 и преобразовать вашу буквальную строку из whcar_t в std::string символов UTF-8.

Если вы используете недавний компилятор, вы можете использовать следующее для создания строкового литерала UTF-8:

u8"ć"

Должно работать следующее:

int main()
{
    std::ifstream input("input.txt");
    std::ofstream output("output.txt");

    if(!(input && output)){
        std::cerr << "file(s) not opened";
        return -1;
    }

    std::string buf;
    std::getline(input, buf);

    output << buf;

    std::cout << buf.find(u8"ć");
}
...