C - 如何从 stdin 正确读取本地化输入?

标签 c setlocale

我需要通过标准输入输入特殊字符,但这样做似乎有问题。我猜 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;
} 

Console output example

最佳答案

尝试修复程序中错误的区域设置是错误的。您应该在您的环境中设置正确的区域设置,并在代码中使用该值,如下所示:

setlocale(LC_ALL, "");

这就是手册页的内容:

On startup of the main program, the portable "C" locale is selected as default. A program may be made portable to all locales by calling:

setlocale(LC_ALL, "");

编辑:

看看你最后的屏幕截图,在读取输入时似乎有些东西混淆了。

情况 1:(没有调用 setlocale 的情况)

...看起来不太有趣。正如在(默认)“C”语言环境中仅包含字符 U+00-U+7E 一样,即使它似乎会产生正确的结果,这或多或少是垃圾输入 - 垃圾输出的情况。 值 0x9F 是编码 Unicode 字符“带有 CARON 的拉丁小写字母 C”(U+010D) č 的代码页 825(请参阅:http://de.wikipedia.org/wiki/Codepage_852)。

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

情况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 字符“LATIN SMALL LETTER Z WITH ACUTE”(U+017A) ź (第二个屏幕截图中的输出)准确地表示为代码页 1250 中的值 0x9f(这是您在使用“原始”字符代码时报告的值)。

不知何故,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)

关于C - 如何从 stdin 正确读取本地化输入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15301129/

相关文章:

c - 为什么 gethostbyname() 在不存在的主机名上不会失败?

php - 如何在PHP数组排序中使用多个sort_flags(使用SORT_LOCALE_STRING,SORT_NATURAL)?

c++ - std::locale::global 是否影响 printf() 函数?

c++ - wstring::find() 不适用于非拉丁符号?

php - 即使语言环境在平台中可用,setlocale php 函数也会返回 false

c - 从二进制文件读入一个 int

c - 重用缓冲区指针_before_ free

c if 语句检查零

swift - 将语言设置为简体中文 (Zh-Hans) 在 IOS9 上不起作用

objective-c - NSZombieEnabled 只适用于 Objective-C 代码吗?