Не удается найти wchar_t, который присутствует в std::wstring

Я играл с 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 ответ

Решение

К несчастью 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"ć");
}
Другие вопросы по тегам