写入包含非 ASCII 字符的字符串 - 仅当字符串是变量时才出错
Write a string with non-ASCII characters in it - error only if string is a variable?
我正在尝试将包含非ASCII字符的字符串写入文件,例如"maçã","pé"等。
我目前正在做这样的事情:
_setmode(_fileno(stdout), _O_U16TEXT);
//I added the line above recently to the question,
//but it was in the code before, I forgot to write it
//I also included some header files, to be able to do that
//can't really remember which, if necessary I'll look it up.
wstring word=L"";
wstring file = L"example_file.txt"
vector<wstring> my_vector;
wofstream my_output(file);
while(word != L".")
{
getline(wcin, word);
if(word!= L".")
my_vector.pushback(word);
}
for(std::vector<wstring>::iterator j=my_vector.begin(); j!=my_vector.end(); j++)
{
my_output << *j << endl;
//element pointed by iterator going through the whole vector
my_output << L("maçã pé") << endl;
}
my_output.close();
现在,如果我输入"maçã","pé"和"."作为单词(只有第一个两个存储在向量中(,文件的输出相当奇怪:
- 我输入的单词(存储在变量中(看起来很奇怪:"ma‡Æ"和"p,";
- 直接存储在代码中的单词看起来完全正常"maçã pé";
我尝试使用wcin >> word
而不是getline(wcin, word)
并写入控制台而不是文件,结果是一样的:错误地写入变量字符串,直接在代码中完美地写入字符串。
我找不到发生这种情况的原因,因此任何帮助将不胜感激。
编辑:我正在使用Windows 7,使用Visual C++ 2010
编辑2:又添加了一行我错过的代码。(就在开头(
编辑3:按照SigTerm的建议,我意识到问题出在输入上:wcin和getline都没有获得正确格式化为变量wstring word
的字符串。所以,问题是,你知道是什么原因造成的或如何解决它吗?
尝试包含
#include <locale>
并在主的开头,写
std::locale::global(std::locale(""));
Windows 使编码变得混乱,因为控制台通常使用"OEM"代码页,而 GUI 应用程序使用"ANSI"代码页。 每个都因所使用的 Windows 的本地化版本而异。在美国 Windows 上,OEM 代码页为 437,ANSI 代码页为 1252。
请记住上述内容,将流设置为正在使用的区域设置可以解决此问题。 如果在控制台中工作,请使用控制台的代码页:
wcin.imbue(std::locale("English_United States.437"));
wcout.imbue(std::locale("English_United States.437"));
但请记住,大多数代码页都是单字节编码,因此只能理解 256 个可能的 Unicode 字符:
wstring word;
wcin.imbue(std::locale("English_United States.437"));
wcout.imbue(std::locale("English_United States.437"));
getline(wcin, word);
wcout << word << endl;
wcout << L"maçã pé" << endl;
这将在控制台上返回:
maça pé
maça pé
代码页 437 不包含 ã
。
在以下情况下,可以从控制台使用代码页 1252:
- 问题
chcp 1252
. - 使用 TrueType 控制台字体,如 Consolas 或 Lucida Console。
- 相反,让溪流充满
English_United States.1252
。
写入文件也有类似的问题。 如果在记事本中查看该文件,它将使用 ANSI 代码页来解释文件中的字节。 因此,即使控制台应用使用代码页 437,如果使用 437 代码页编写,记事本也会错误地显示文件。 在代码页 1252 中写入文件也无济于事,因为这两个代码页不解释同一组 Unicode 代码点。 此问题的一些答案是获取不同的文件查看器,例如Notepad++或以支持所有Unicode字符的UTF-8编写文件。
您遇到的问题与此处描述的问题相反。
核心原因是相同的:"ASCII">1 范围 128-256 中的字符不如范围 32-127 中的字符标准化。大多数 Windows 应用程序,无论它们使用"Unicode"还是"ANSI"字符串,都使用与 Unicode 指定的代码和字符之间的相同映射。但是,由于主要历史原因,控制台使用单独的代码到字符映射,通常称为"代码页"。使用的确切表取决于 Windows 的语言和配置。对于美国英语计算机,这是 OEM 437 代码页。
在控制台中键入 ç
时,实际上是在输入字符代码 135,因为这是控制台使用的 437 代码页中分配给该字符的代码。Windows 的其余部分将 Unicode 表中描述的字符代码解释为字符‡
。
您可以使用OemToChar
(此处的文档(将通过控制台输入的文本转换为 Unicode 编码的相应字符串。
有关其他背景信息,请参阅此处的回答。
1 是的,这个范围是技术性的,不是 ASCII,但足够接近。我也在整个过程中使用了通常的非正式(和技术上错误(的Unicode定义。
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- 如果用户输入无效,如何使用字符串变量-C++重复输入命令
- 从字符串变量中逐字符读取单词
- 对函数 PlaySound 使用字符串变量
- C++中的字符串变量
- 字符串变量,比如说"字符串str",可以直接复制到数组中吗?
- 我可以用字符串变量而不是它的名字创建容器吗? C++
- 字符串变量的大小
- 为什么我的字符串变量没有打印完整的字符串?
- 字符串变量未更新 c++
- 如何使用 setfill 和 setw 在字符串变量中存储十六进制值
- 在.cpp文件之间传递全局字符串变量?
- 字符串变量顺序
- 为什么可以将整数分配给字符串变量?
- 在qt创建器中调试时如何访问字符串变量的完整值?
- 将字符串变量分配给无符号字符变量
- 在 c++ 中使用字符串变量选择静态类结构,而不带对象
- C++我应该用什么来保存格式化为字符串变量(如sprintf())的文件
- 我有一个字符串变量单词= "APA"
- 将字符串变量从 bash 脚本传递到根宏