我需要通过stdin输入特殊字符,这样做似乎有问题。我猜fgetws()不支持cp852(我操作系统的标准控制台代码页,Win 7 x64顺便说一句)。我应该使用cp1250还是别的什么?我尝试在cmd.exe中使用chcp 1250,但这只持续到我关闭命令提示符。我在Visual C上。
#include <stdio.h>
#include <locale.h>
int main()
{
wchar_t query[64];
setlocale(LC_ALL, "croatian");
wprintf(L"Insert special characters: ");
fgetws(query, 64, stdin);
fputws(query, stdout);
putchar('\n');
return 0;
}
答案 0 :(得分:2)
尝试在程序中修复错误的区域设置是错误的。您应该在您的环境中设置正确的区域设置,并在代码中使用此值,如:
setlocale(LC_ALL, "");
这就是man-page所说的:
在启动主程序时,选择便携式“C”语言环境 默认。通过调用:
,程序可以移植到所有语言环境setlocale(LC_ALL,“”);
编辑:
看一下你的最后一个截图给我看来,在阅读输入时似乎有些混乱。
案例1:(没有调用setlocale
的那个人)
......似乎并不太有趣。在(默认)“C”语言环境中只包含字符U + 00-U + 7E,即使它似乎以产生正确的结果,这或多或少是垃圾输入 - 垃圾输出的情况。
值0x9F是代码页825(参见:http://de.wikipedia.org/wiki/Codepage_852)编码Unicode字符'LATIN SMALL LETTER C WITH CARON'(U + 010D)č
。
来回传递原始值,如果再次向终端写入相同的字节,则会产生相同的输出,这并不奇怪。
案例2:
......看起来更有趣。
值0x17a是unicode字符'LATIN SMALL LETTER Z WITH ACUTE'(U + 017A)ź
的UTF-16编码,完全匹配截图中显示的输出。由于fputsw似乎在核心地将其映射到终端编码,因此问题似乎是输入未被正确读取。
只是为了确保在进行更改后没有任何困惑 - 你正在运行这样的代码吗?
#include <stdio.h>
#include <locale.h>
int main () {
wchar_t query[64];
setlocale (LC_ALL, "");
if (fgetws(query, 64, stdin) == NULL)
return -1;
fputws(query, stdout);
putchar('\n');
return 0;
}
编辑:
我忘了提及你测试中最有趣的事情之一:unicode字符'拉丁文小写字母带有急促'(U + 017A)ź
(你的第二个截图中的一个输出)完全代表作为值0x9f
(这是您在代码页1250中使用“原始”字符代码时报告的值)。
fgetws似乎使用代码页1250而不是代码页825来解释字符代码。
至于我,似乎问题仍然是区域设置以某种方式混淆了。您可能应该尝试运行以下代码并查看报告的区域设置。
#include <locale.h>
#include <stdio.h>
int main (int argc, char *argv[]) {
char *locale;
setlocale (LC_ALL, "");
if ((locale = setlocale (LC_ALL, NULL)) == NULL)
return -1;
printf ("%s\n", locale);
return 0;
}
在我的系统上,例如,这给出了输出:es_ES.utf8
有趣的部分是点''后面的那个。因为它指定了字符编码(上面给出的例子中的utf8)。
要检查的另一件事可能是您正在使用的Visual Studio的程序版本,因为在旧版本中设置默认语言环境似乎存在错误。 (见:http://connect.microsoft.com/VisualStudio/feedback/details/709505/setlocale-lc-all-returns-incorrect-default-system-locale)
答案 1 :(得分:0)
谢谢mikyra,试图提供帮助。 解决方法是将setlocale显式地作为第二个参数提供给我的控制台的默认代码页。像这样:
setlocale( LC_ALL, ".852" );
希望不会出现新问题。谢谢,MSDN。