Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.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中读取和打印Unicode和UTF-8编码_C_Windows_Unicode_Character Encoding_Console - Fatal编程技术网

在C中读取和打印Unicode和UTF-8编码

在C中读取和打印Unicode和UTF-8编码,c,windows,unicode,character-encoding,console,C,Windows,Unicode,Character Encoding,Console,我正在使用Windows XP。 我想读取ASCII、UTF-8和Unicode编码的文件,并在标准输出上打印字符串。 我试图使用wchar.h中的函数,如fgetwc()/fputwc()和fgetws()/fputws(),它们在ASCII上工作,但在文件为UTF-8或Unicode时不工作。不打印特定于语言的字符,当文件使用Unicode时,它只打印方框和第一个字母。 有没有办法用纯C语言编写一个程序,它可以读取文件、比较字符串并在标准输出上正确打印出来,而不考虑输入程序的文件的编码 有没

我正在使用Windows XP。
我想读取ASCII、UTF-8和Unicode编码的文件,并在标准输出上打印字符串。
我试图使用wchar.h中的函数,如fgetwc()/fputwc()fgetws()/fputws(),它们在ASCII上工作,但在文件为UTF-8或Unicode时不工作。不打印特定于语言的字符,当文件使用Unicode时,它只打印方框和第一个字母。
有没有办法用纯C语言编写一个程序,它可以读取文件、比较字符串并在标准输出上正确打印出来,而不考虑输入程序的文件的编码

有没有办法用纯C语言编写一个程序,它可以读取文件、比较字符串并在标准输出上正确打印出来,而不考虑输入程序的文件的编码


不,程序显然也要告诉我们文件的编码。在内部,您可以选择使用UTF-8中的多字节字符串或宽字符串来表示文件的数据。

因为您在Windows上,关键是要使用函数写出字符串,首先要组装要写出的UTF-16字符序列。(一次可能只需写入几千字节的字符。)当然,可以使用
GetStdHandle
获取控制台句柄


更难的是确定文件的编码。幸运的是,您不需要区分ASCII和UTF-8,因为后者是前者的严格超集。但对于任何其他单字节编码,您都需要猜测。一些UTF-8文件(在Windows上比在其他地方更可能如此)在文件的开头有一个UTF-8编码的字节顺序标记;这很糟糕,因为BOM实际上不应该与UTF-8一起使用,但如果存在的话,它是一个强有力的指标。(发现UTF-16更容易,因为它应该有一个字节顺序标记,或者你可以从NUL(0)字节的存在中猜出来。)

这里有一段代码,我用来打印Unicode的ASCII子集之外的各种字符(包含解决Open Watcom编译器的printf()实现中可能出现的错误的方法):


在Windows XP中,我没有找到一种直接将UTF-16代码点打印到控制台的方法,该方法的工作原理与上述方法相同。

是的,有一种方法,但是“正确打印”对您意味着什么?它比什么更有效?我的意思是从比较的文件中读取非ASCII字母,例如觅čćđž,并打印在标准输出上。“Unicode”不是编码。@比利:是的,Windows也使用UTF-16表示宽字符串/字符。我从来没有说过它是“无效的”(不管这意味着什么)。你的文本说“UTF-8中的多字节字符串或宽字符串”--UTF-16和UTF-8一样都是“多字节”,但它也比字符更宽。(真正的“宽”字符串使用UTF-32/UCS-4)@Billy“多字节字符”和“宽字符”具有精确定义的含义(参见C99中的3.7.2和3.7.3),我指的就是这个意思。根据C,多字节字符和宽字符有定义的含义。它们对于Unicode没有意义。可以建立猜测编码的启发式方法,但很难做到完美。非常好的编码,谢谢。它让我了解了很多Windows特定编程的内幕。
// Compile with Open Watcom C/C++ 1.9: wcl386 cons-utf8.c

#include <windows.h>
#include <stdio.h>
#include <stddef.h>

// Workarounds for printf() not printing multi-byte (UTF-8) strings
// with Open Watcom C/C++ 1.7-1.9.
// 0 - no workaround for printf()
// 1 - setbuf(stdout, NULL) before printf()
// 2 - fflush(stdout) after printf()
// 3 - WriteConsole() instead of printf()
#define PRINT_WORKAROUND 03

int main(void)
{
  DWORD err, i, j;
  // Code point ranges of characters to print
  static const DWORD ranges[][2] =
  {
    { 0x0A0, 0x0FF }, // Latin chars with diacritic marks + some others
    { 0x391, 0x3CE }, // Greek chars
    { 0x410, 0x44F }  // Cyrillic chars
  };

#if PRINT_WORKAROUND == 1
  setbuf(stdout, NULL);
#endif

  if (!SetConsoleOutputCP(CP_UTF8))
  {
    err = GetLastError();
    printf("SetConsoleOutputCP(CP_UTF8) failed with error 0x%X\n", err);
    goto Exit;
  }

  printf("Workaround: %d\n", PRINT_WORKAROUND);

  for (j = 0; j < sizeof(ranges) / sizeof(ranges[0]); j++)
  {
    for (i = ranges[j][0]; i <= ranges[j][1]; i++)
    {
      char str[8];
      int sz;
      wchar_t wstr[2];
      wstr[0] = i;
      wstr[1] = 0;

      sz = WideCharToMultiByte(CP_UTF8,
                               0,
                               wstr,
                               -1,
                               str,
                               sizeof(str),
                               NULL,
                               NULL);
      if (sz <= 0)
      {
        err = GetLastError();
        printf("WideCharToMultiByte() failed with error 0x%X\n", err);
        goto Exit;
      }

#if PRINT_WORKAROUND < 3
      printf("%s", str);
#if PRINT_WORKAROUND == 2
      fflush(stdout);
#endif
#else
      WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),
                   str,
                   sz - 1,
                   &err,
                   NULL);
#endif
    }

    printf("\n");
  }
  printf("\n");

Exit:

  return 0;
}
C:\>cons-utf8.exe

Workaround: 3
 ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ΢ΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ
АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя