Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C-如何正确读取标准输入的本地化输入?_C_Setlocale - Fatal编程技术网

C-如何正确读取标准输入的本地化输入?

C-如何正确读取标准输入的本地化输入?,c,setlocale,C,Setlocale,我需要通过stdin输入特殊字符,这样做似乎有问题。我猜fgetws()不支持cp852(我的操作系统的标准控制台代码页,Win7 x64 btw)。我应该用cp1250还是别的什么?我尝试在cmd.exe中使用chcp 1250,但这种情况只会持续到关闭命令提示符。我使用的是visualc #include <stdio.h> #include <locale.h> int main() { wchar_t query[64]; setlocale(L

我需要通过stdin输入特殊字符,这样做似乎有问题。我猜fgetws()不支持cp852(我的操作系统的标准控制台代码页,Win7 x64 btw)。我应该用cp1250还是别的什么?我尝试在cmd.exe中使用chcp 1250,但这种情况只会持续到关闭命令提示符。我使用的是visualc

#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;
} 
#包括
#包括
int main()
{
wchar_t查询[64];
setlocale(LC_ALL,“克罗地亚语”);
wprintf(L“插入特殊字符:”);
fgetws(查询,64,标准输入);
fputws(查询、标准输出);
putchar('\n');
返回0;
} 

试图修复程序中错误的区域设置是错误的。您只需在环境中设置正确的语言环境,并在代码中使用此值,如:

setlocale(LC_ALL, "");
这是手册页所说的:

主程序启动时,选择可移植的“C”语言环境作为 违约可通过调用以下命令使程序可移植到所有地区:

setlocale(LC_ALL,“”)

编辑:

看一看你最后的截图,在阅读输入时,似乎有什么东西弄混了

案例1:(未调用
setlocale的案例)

。。。看起来不太有趣。在(默认)“C”语言环境中,即使生成正确的结果,也只包含字符U+00-U+7E,这或多或少是垃圾输入-垃圾输出的情况。 值0x9F是编码Unicode字符“带CARON的拉丁小写字母C”(U+010D)
č
的代码页825(请参阅:)

通过来回传递原始值,如果再次将相同的字节写入终端,则会生成相同的输出,这一点也不奇怪

案例2:

。。。看起来有点有趣。 值0x17a是unicode字符“带锐音符的拉丁小写字母Z”(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;
}
例如,在我的系统上,这给出了输出:
es_es.utf8
有趣的部分是点“.”后面的部分,因为这指定了字符编码(上面给出的示例中的utf8)


另一件需要检查的事情可能是您正在使用的VisualStudio的程序版本,因为在旧版本中设置默认语言环境似乎存在错误。(请参阅:)

谢谢米凯拉的帮助。 通过显式地将我的控制台的默认代码页作为第二个参数提供给setlocale来解决。像这样:

setlocale( LC_ALL, ".852" );

希望不会出现新的问题。谢谢。

所以说“特殊字符”是指unicode吗?说错了,基本上我指的是非ASCII字符。您的区域设置是什么。如果您的操作系统上有这样的工具,您应该能够使用
locale
命令查看设置。在Region and Language->administration下,它会显示“非Unicode程序的当前语言-克罗地亚语(Croatian)”。在命令提示符中键入chcp显示“活动代码页-852”。也许我需要将其设置为1250。更奇怪的是,代码页852显然支持您试图显示的glyph,正如链接图像中的输入行所示。我猜在从代码页852转换到UTF-16或从UTF-16转换回代码页852的过程中会出现一些问题。可能将读取字符转储为十六进制可以提供一些见解。windows wchar中的AFAIK应以UTF-16编码。因此,您可能会检查从代码页852到wchar\u t的转换是否得到正确处理。这有点超出我的能力范围,因为我学习C语言才六个月左右。但我会尽我所能。其他人在gcc/MinGW上试用过,效果很好。这就是我使用setlocale函数前后的情况。我使用了wprintf的\X格式说明符-我必须
#包括
,gcc才能接受
wchar\u t
。用户肯定会因此打败你-但如果它起作用。。。为什么不呢?这肯定比我预想的更有趣。因此,我应该等待2天接受我自己的解决方案,还是应该接受你的解决方案,因为你已经彻底解释了这种情况下的I/O过程,尽管没有实际的解决方案?顺便说一句,为什么我要检查stdin是否为NULL-可能只检查\n输入?尽管可能有点神秘
if(fgetws(query,64,stdin)==NULL)
没有检查stdin是否为NULL,但fgetws的返回值在尝试读取时发生错误时将为NULL。如果您只打算将该程序用于美学之外的目的,那么将字符编码硬编码到CP852的“解决方案”并没有错。另一方面,如果其他用户也希望运行该程序,那么当使用除cp 852以外的任何其他字符编码时,他们只会得到无用的输入,因此可能应该以预期的方式使用setlocale。@mikyra是的,我知道这不是一个“真正的”解决方案,但是这个程序不打算被我以外的任何人使用,所以它现在就可以了。再次感谢你。您的代码给了我“Croatian_Croatia.1250”。然后,正如前面所说的,读取的
0x9f
应该表示
ź
。您的控制台设置是否可能与您的区域设置不匹配<不带参数的code>chcp
应显示控制台当前使用的代码页。如果一切正常的话,这必须是
1250
。如果显示852之类的内容,则此不匹配将是正确的修复位置。通过将您的语言环境设置为与控制台的代码页匹配的语言环境,或者将控制台使用的cp调整为您的语言环境的cp。在启动程序之前,您可以通过执行
chcp 1250
进行检查。
setlocale( LC_ALL, ".852" );