【问题标题】:C++ ifstream and "umlauts"C++ ifstream 和“变音符号”
【发布时间】:2012-07-23 08:21:24
【问题描述】:

我对 C++ 中的“元音变音”(字母 ä、ü、ö、...)和 ifstream 有疑问。

我使用 curl 下载一个 html 页面,并使用 ifstream 逐行读取下载的文件并从中解析出一些数据。这一切顺利,直到我有如下一行:

te="Olimpija Laibach - Tromsö";
te="Burghausen - Münster";

我的代码解析这些行并将其输出如下:

Olimpija Laibach vs. Troms?
Burghausen vs. M?nster

直接从代码中输出变音符号之类的工作:

cout << "öäü" << endl; // This works fine

我的代码看起来有点像这样:

ifstream fin("file");

while(!(fin.eof())) {
    getline(fin, line, '\n');
    int pos = line.find("te=");
    if(pos >= 0) {
         pos = line.find(" - ");
         string team1 = line.substr(4,pos-4);
         string team2 = line.substr(pos+3, line.length()-pos-6);
         cout << team1 << " vs. " << team2 << endl;
   }
}

编辑: 奇怪的是相同的代码(唯一改变的是源和分隔符)适用于另一个文本输入文件(相同的过程:使用 curl 下载,使用 ifstream 读取) .解析输出如下一行是没有问题的:

<span id="...">Fernwärme Vienna</span>

【问题讨论】:

  • 一旦您知道输入的编码是什么,cppreference 中的一些示例可能会有所帮助,例如here
  • 我刚刚编辑并扩展了我的问题。我不明白为什么(几乎)相同的代码与另一个输入一起工作。
  • 通常std::cout &lt;&lt; "öäü" &lt;&lt; std::endl;也不起作用。

标签: c++ ifstream


【解决方案1】:

fin 中嵌入的语言环境是什么?在您显示的代码中,它会 是全局语言环境,如果你没有重置它,它是"C"

如果您身处盎格鲁-撒克逊世界之外的任何地方——还有弦乐 你表明你是——你做的第一件事之一 main 应该是

std::locale::global( std::locale( "" ) );

这将设置全局语言环境(因此任何流的默认语言环境 稍后打开)到在周围环境中使用的语言环境。 (正式地,对于实现定义的本地环境,但在 练习,无论用户使用什么。)在"C" 语言环境中,编码 几乎总是 ASCII; ASCII 不识别元音变音,并且根据 按照标准,输入中的非法编码应替换为 实现定义的字符(IIRC——已经有一段时间了 我实际上已经重读了这一部分)。当然,在输出中,你不是 应该有任何未知字符,所以实现不 检查它们,然后通过。

由于std::cin等被打开之前你还有机会设置 全局语言环境,您必须专门为它们注入 std::locale( "" )

如果这不起作用,您可能需要找到一些特定的语言环境 使用。

【讨论】:

  • 计算 HTML 的编码并非易事。 (在最好的情况下,找到像&lt;meta http-equiv="Content-Type" content="text/html;charset=UTF-8"&gt; 这样的行)使用用户的语言环境只是一个更好的猜测。
  • 不幸的是,这没有帮助。包含std::locale::global( std::locale( "de_DE.UTF-8" ) ); 作为main 中的第一行,但输出保持不变。值得一提的是,我正在使用美国的 Amazon EC2 实例来编译和运行代码。
  • @mike:UTF-8 实际上是输入编码吗? (它可能是 ISO-8859-1 或 ISO-8859-15,或者完全不同的东西。)您使用的系统实际上支持 de_DE.UTF-8 吗?
  • 在不适合我的页面的 html 中发现以下行:&lt;meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"&gt;。将语言环境更改为std::locale::global( std::locale( "de_DE.iso88591" ) );,但问题仍然存在。与std::locale::global( std::locale( "de_DE.iso885915@euro" ) ); 也没有区别。
  • @MSalters 如果您正在阅读 HTML,则标题应包含编码指示,您可以 imbue 相应的语言环境。
猜你喜欢
  • 2017-01-19
  • 1970-01-01
  • 2010-12-16
  • 2011-03-24
  • 2010-10-23
  • 2016-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多