【问题标题】:fstream not working properly with russian text?fstream 不能与俄语文本一起正常工作?
【发布时间】:2021-11-08 21:15:21
【问题描述】:

我经常使用俄语,我一直在尝试从带有输入流的文件中获取数据。这是代码,它应该只输出包含不超过5个字符的单词。

#include <iostream>
#include <fstream>
#include <string>
#include <Windows.h>
using namespace std;
int main()
{
    setlocale(LC_ALL, "ru_ru.utf8");
    ifstream input{ "in_text.txt" };
    if (!input) {
        cerr << "Ошибка при открытии файла" << endl;
        return 1;
    }
    cout << "Вывод содержимого файла: " << "\n\n";
    string line{};
    while (input >> line) {
        if (line.size() <= 5)
            cout << line << endl;
    }
    cout << endl;

    input.close();
    return 0;
}

问题来了:

我注意到输出并没有选择所有实际上包含少于 5 个字符的单词。所以我做了一个简单的测试,用英语单词“Test”和俄语翻译“тест”,字符数相同。所以我的文本文件看起来像这样:

Test тест

我以前用调试器来查看程序如何运行,它会打印出英文单词并留下俄文。我不明白为什么会这样。

附:当我将代码更改为if (line.size() &lt;= 8) 时,它会将它们都打印出来。很奇怪

我想我搞砸了我的系统区域设置,我不知道。我曾经尝试过使用std::locale 没有真正理解它,也许这对我的电脑有什么影响,我不太确定。请帮忙

【问题讨论】:

  • 我认为这可以帮助你。 docs.microsoft.com/en-us/windows/win32/learnwin32/… 基于您使用 Windows 并使用特殊字符。
  • utf8 表示俄语字形由 2 个或更多字节编码,但由于 string.size() 计算的是字节数,而不是字符数,因此您会得到错误的计数。
  • @MichaelVeksler 你建议如何解决这个问题?我以前使用过 setlocale(LC_ALL, "Russian") 但最近由于某种原因它没有工作
  • 使用宽字符、wcout、wstring、L"Ошибка при открытии файла" 等可能会有更好的效果。我对 C++ 中的非 ASCII 文本没有足够的经验来推荐最佳实践。我会使用与您相同的代码,仅将字符串转换为 wstring 并测试其大小。见stackoverflow.com/questions/2573834/…
  • @TedLyngmo 是的,没问题

标签: c++ fstream


【解决方案1】:

我对此非常不确定,但使用 codecvt_utf8wstring_convert 似乎可行:

#include <codecvt>   // codecvt_utf8
#include <string>
#include <iostream>
#include <locale>    // std::wstring_convert

int main() {
    // ...

    while (input >> line) {
        // convert the utf8 encoded `line` to utf32 encoding:
        std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> u8_to_u32;
        std::u32string u32s = u8_to_u32.from_bytes(line);

        if (u32s.size() <= 5)           // check the utf32 length
            std::cout << line << '\n';  // but print the utf8 encoded string
    }

    // ...
}

Demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-10
    • 2014-07-01
    • 1970-01-01
    • 2016-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多