如何在ANSI C中打印重音字符(如áéíóú)

sea*_*ean 10 c printf ansi non-ascii-characters

我试着printf用一些重音字符,例如á é í ó ú:

printf("my name is Seán\n");

DEVC++ IDE中的文本编辑器显示它们很好 - 即源代码看起来很好.我想我需要一些其他库stdio.h,也许还有一些正常的变体printf.

我正在使用在Windows XP上运行的IDE Bloodshed DEVC.

Ale*_*nze 6

也许最好的方法是使用 Unicode。

\n\n

就是这样...

\n\n

首先,手动将控制台字体设置为“Consolas”或“Lucida Console”或您可以选择的任何 True-Type Unicode 字体(“光栅字体”可能不起作用,这些字体不是 Unicode 字体,尽管它们可能包含您\有兴趣)。

\n\n

接下来,将控制台代码页设置为 65001 (UTF-8),并使用SetConsoleOutputCP(CP_UTF8).

\n\n

然后使用 .txt 将文本转换为 UTF-8(如果还不是 UTF-8)WideCharToMultiByte(CP_UTF8, ...)

\n\n

最后调用WriteConsoleA()输出UTF-8文本。

\n\n

这是一个可以为您完成所有这些事情的小函数,它是 的“改进”变体wprintf()

\n\n
int _wprintf(const wchar_t* format, ...)\n{\n  int r;\n  static int utf8ModeSet = 0;\n  static wchar_t* bufWchar = NULL;\n  static size_t bufWcharCount = 256;\n  static char* bufMchar = NULL;\n  static size_t bufMcharCount = 256;\n  va_list vl;\n  int mcharCount = 0;\n\n  if (utf8ModeSet == 0)\n  {\n    if (!SetConsoleOutputCP(CP_UTF8))\n    {\n      DWORD err = GetLastError();\n      fprintf(stderr, "SetConsoleOutputCP(CP_UTF8) failed with error 0x%X\\n", err);\n      utf8ModeSet = -1;\n    }\n    else\n    {\n      utf8ModeSet = 1;\n    }\n  }\n\n  if (utf8ModeSet != 1)\n  {\n    va_start(vl, format);\n    r = vwprintf(format, vl);\n    va_end(vl);\n    return r;\n  }\n\n  if (bufWchar == NULL)\n  {\n    if ((bufWchar = malloc(bufWcharCount * sizeof(wchar_t))) == NULL)\n    {\n      return -1;\n    }\n  }\n\n  for (;;)\n  {\n    va_start(vl, format);\n    r = vswprintf(bufWchar, bufWcharCount, format, vl);\n    va_end(vl);\n\n    if (r < 0)\n    {\n      break;\n    }\n\n    if (r + 2 <= bufWcharCount)\n    {\n      break;\n    }\n\n    free(bufWchar);\n    if ((bufWchar = malloc(bufWcharCount * sizeof(wchar_t) * 2)) == NULL)\n    {\n      return -1;\n    }\n    bufWcharCount *= 2;\n  }\n\n  if (r > 0)\n  {\n    if (bufMchar == NULL)\n    {\n      if ((bufMchar = malloc(bufMcharCount)) == NULL)\n      {\n        return -1;\n      }\n    }\n\n    for (;;)\n    {\n      mcharCount = WideCharToMultiByte(CP_UTF8,\n                                       0,\n                                       bufWchar,\n                                       -1,\n                                       bufMchar,\n                                       bufMcharCount,\n                                       NULL,\n                                       NULL);\n      if (mcharCount > 0)\n      {\n        break;\n      }\n\n      if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)\n      {\n        return -1;\n      }\n\n      free(bufMchar);\n      if ((bufMchar = malloc(bufMcharCount * 2)) == NULL)\n      {\n        return -1;\n      }\n      bufMcharCount *= 2;\n    }\n  }\n\n  if (mcharCount > 1)\n  {\n    DWORD numberOfCharsWritten, consoleMode;\n\n    if (GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &consoleMode))\n    {\n      fflush(stdout);\n      if (!WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE),\n                         bufMchar,\n                         mcharCount - 1,\n                         &numberOfCharsWritten,\n                         NULL))\n      {\n        return -1;\n      }\n    }\n    else\n    {\n      if (fputs(bufMchar, stdout) == EOF)\n      {\n        return -1;\n      }\n    }\n  }\n\n  return r;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

下面测试这个功能:

\n\n
_wprintf(L"\\xA0\\xA1\\xA2\\xA3\\xA4\\xA5\\xA6\\xA7"\n         L"\\xA8\\xA9\\xAA\\xAB\\xAC\\xAD\\xAE\\xAF"\n         L"\\xB0\\xB1\\xB2\\xB3\\xB4\\xB5\\xB6\\xB7"\n         L"\\xB8\\xB9\\xBA\\xBB\\xBC\\xBD\\xBE\\xBF"\n         L"\\n"\n         L"\\xC0\\xC1\\xC2\\xC3\\xC4\\xC5\\xC6\\xC7"\n         L"\\xC8\\xC9\\xCA\\xCB\\xCC\\xCD\\xCE\\xCF"\n         L"\\xD0\\xD1\\xD2\\xD3\\xD4\\xD5\\xD6\\xD7"\n         L"\\xD8\\xD9\\xDA\\xDB\\xDC\\xDD\\xDE\\xDF"\n         L"\\n"\n         L"\\xE0\\xE1\\xE2\\xE3\\xE4\\xE5\\xE6\\xE7"\n         L"\\xE8\\xE9\\xEA\\xEB\\xEC\\xED\\xEE\\xEF"\n         L"\\xF0\\xF1\\xF2\\xF3\\xF4\\xF5\\xF6\\xF7"\n         L"\\xF8\\xF9\\xFA\\xFB\\xFC\\xFD\\xFE\\xFF"\n         L"\\n");\n\n_wprintf(L"\\x391\\x392\\x393\\x394\\x395\\x396\\x397"\n         L"\\x398\\x399\\x39A\\x39B\\x39C\\x39D\\x39E\\x39F"\n         L"\\x3A0\\x3A1\\x3A2\\x3A3\\x3A4\\x3A5\\x3A6\\x3A7"\n         L"\\x3A8\\x3A9\\x3AA\\x3AB\\x3AC\\x3AD\\x3AE\\x3AF\\x3B0"\n         L"\\n"\n         L"\\x3B1\\x3B2\\x3B3\\x3B4\\x3B5\\x3B6\\x3B7"\n         L"\\x3B8\\x3B9\\x3BA\\x3BB\\x3BC\\x3BD\\x3BE\\x3BF"\n         L"\\x3C0\\x3C1\\x3C2\\x3C3\\x3C4\\x3C5\\x3C6\\x3C7"\n         L"\\x3C8\\x3C9\\x3CA\\x3CB\\x3CC\\x3CD\\x3CE"\n         L"\\n");\n\n_wprintf(L"\\x410\\x411\\x412\\x413\\x414\\x415\\x401\\x416\\x417"\n         L"\\x418\\x419\\x41A\\x41B\\x41C\\x41D\\x41E\\x41F"\n         L"\\x420\\x421\\x422\\x423\\x424\\x425\\x426\\x427"\n         L"\\x428\\x429\\x42A\\x42B\\x42C\\x42D\\x42E\\x42F"\n         L"\\n"\n         L"\\x430\\x431\\x432\\x433\\x434\\x435\\x451\\x436\\x437"\n         L"\\x438\\x439\\x43A\\x43B\\x43C\\x43D\\x43E\\x43F"\n         L"\\x440\\x441\\x442\\x443\\x444\\x445\\x446\\x447"\n         L"\\x448\\x449\\x44A\\x44B\\x44C\\x44D\\x44E\\x44F"\n         L"\\n");\n
Run Code Online (Sandbox Code Playgroud)\n\n

并且应该在控制台中产生以下文本:

\n\n
\xc2\xa0\xc2\xa1\xc2\xa2\xc2\xa3\xc2\xa4\xc2\xa5\xc2\xa6\xc2\xa7\xc2\xa8\xc2\xa9\xc2\xaa\xc2\xab\xc2\xac\xc2\xad\xc2\xae\xc2\xaf\xc2\xb0\xc2\xb1\xc2\xb2\xc2\xb3\xc2\xb4\xc2\xb5\xc2\xb6\xc2\xb7\xc2\xb8\xc2\xb9\xc2\xba\xc2\xbb\xc2\xbc\xc2\xbd\xc2\xbe\xc2\xbf\n\xc3\x80\xc3\x81\xc3\x82\xc3\x83\xc3\x84\xc3\x85\xc3\x86\xc3\x87\xc3\x88\xc3\x89\xc3\x8a\xc3\x8b\xc3\x8c\xc3\x8d\xc3\x8e\xc3\x8f\xc3\x90\xc3\x91\xc3\x92\xc3\x93\xc3\x94\xc3\x95\xc3\x96\xc3\x97\xc3\x98\xc3\x99\xc3\x9a\xc3\x9b\xc3\x9c\xc3\x9d\xc3\x9e\xc3\x9f\n\xc3\xa0\xc3\xa1\xc3\xa2\xc3\xa3\xc3\xa4\xc3\xa5\xc3\xa6\xc3\xa7\xc3\xa8\xc3\xa9\xc3\xaa\xc3\xab\xc3\xac\xc3\xad\xc3\xae\xc3\xaf\xc3\xb0\xc3\xb1\xc3\xb2\xc3\xb3\xc3\xb4\xc3\xb5\xc3\xb6\xc3\xb7\xc3\xb8\xc3\xb9\xc3\xba\xc3\xbb\xc3\xbc\xc3\xbd\xc3\xbe\xc3\xbf\n\xce\x91\xce\x92\xce\x93\xce\x94\xce\x95\xce\x96\xce\x97\xce\x98\xce\x99\xce\x9a\xce\x9b\xce\x9c\xce\x9d\xce\x9e\xce\x9f\xce\xa0\xce\xa1\xce\xa2\xce\xa3\xce\xa4\xce\xa5\xce\xa6\xce\xa7\xce\xa8\xce\xa9\xce\xaa\xce\xab\xce\xac\xce\xad\xce\xae\xce\xaf\xce\xb0\n\xce\xb1\xce\xb2\xce\xb3\xce\xb4\xce\xb5\xce\xb6\xce\xb7\xce\xb8\xce\xb9\xce\xba\xce\xbb\xce\xbc\xce\xbd\xce\xbe\xce\xbf\xcf\x80\xcf\x81\xcf\x82\xcf\x83\xcf\x84\xcf\x85\xcf\x86\xcf\x87\xcf\x88\xcf\x89\xcf\x8a\xcf\x8b\xcf\x8c\xcf\x8d\xcf\x8e\n\xd0\x90\xd0\x91\xd0\x92\xd0\x93\xd0\x94\xd0\x95\xd0\x81\xd0\x96\xd0\x97\xd0\x98\xd0\x99\xd0\x9a\xd0\x9b\xd0\x9c\xd0\x9d\xd0\x9e\xd0\x9f\xd0\xa0\xd0\xa1\xd0\xa2\xd0\xa3\xd0\xa4\xd0\xa5\xd0\xa6\xd0\xa7\xd0\xa8\xd0\xa9\xd0\xaa\xd0\xab\xd0\xac\xd0\xad\xd0\xae\xd0\xaf\n\xd0\xb0\xd0\xb1\xd0\xb2\xd0\xb3\xd0\xb4\xd0\xb5\xd1\x91\xd0\xb6\xd0\xb7\xd0\xb8\xd0\xb9\xd0\xba\xd0\xbb\xd0\xbc\xd0\xbd\xd0\xbe\xd0\xbf\xd1\x80\xd1\x81\xd1\x82\xd1\x83\xd1\x84\xd1\x85\xd1\x86\xd1\x87\xd1\x88\xd1\x89\xd1\x8a\xd1\x8b\xd1\x8c\xd1\x8d\xd1\x8e\xd1\x8f\n
Run Code Online (Sandbox Code Playgroud)\n\n

我不知道您的 IDE 在 .c/.cpp 文件中存储非 ASCII 字符的编码,也不知道您的编译器在遇到非 ASCII 字符时会做什么。这部分你应该自己弄清楚。

\n\n

只要您提供_wprintf()正确编码的 UTF-16 文本或WriteConsoleA()使用正确编码的 UTF-8 文本进行调用,一切就应该可以正常工作。

\n\n

PS 有关控制台字体的一些详细信息可以在这里找到。

\n


rod*_*igo 4

Windows 控制台在字符编码方面通常被认为严重损坏。例如,您可以在此处阅读有关此问题的信息。

问题是Windows通常使用ANSI代码页(假设您在西欧或美国Windows-1252),但控制台使用OEM代码页(相同假设下的CP850)。

您有多种选择:

  • 在写入之前将文本转换为 CP850(请参阅CharToOem())。缺点是,如果用户将输出重定向到文件 ( > file.txt) 并使用记事本等打开该文件,他会看到错误。
  • 更改控制台的代码页:您需要选择 TTF 控制台字体(例如 Lucida Console)并使用命令chcp 1252
  • 使用 UNICODE 文本和wprintf():无论如何,您都需要 TTF 控制台字体。