Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.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
在cmd上打印到stderr无法打印非ASCII UTF-8文本的第一个字符_C_Windows_Utf 8_Printf_Stderr - Fatal编程技术网

在cmd上打印到stderr无法打印非ASCII UTF-8文本的第一个字符

在cmd上打印到stderr无法打印非ASCII UTF-8文本的第一个字符,c,windows,utf-8,printf,stderr,C,Windows,Utf 8,Printf,Stderr,这就是我的代码的样子: #include <windows.h> #include <stdio.h> int main() { SetConsoleCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8); HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_FONT_INFOEX cfie; ZeroMemory(&cfie, s

这就是我的代码的样子:

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

int main()
{
    SetConsoleCP(CP_UTF8);
    SetConsoleOutputCP(CP_UTF8);

    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_FONT_INFOEX cfie;
    ZeroMemory(&cfie, sizeof(cfie));
    cfie.cbSize = sizeof(cfie);
    lstrcpyW(cfie.FaceName, L"Lucida Console");
    SetCurrentConsoleFontEx(hStdOut, 0, &cfie);

    fprintf(stderr, "нијe\n");
}
当打印行被替换为:
printf(“ајe\n”)

输出是预期的:

нијe

我可能应该提到,我用MinGW GCC编译了它,并在CMD中运行了它。

只有
SetConsoleOutputCP()
对我有效。即使是“Consolas”作为字体也能提供正确的字符

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

int main()
{
    fprintf(stderr, "нијe\n");
    SetConsoleOutputCP(CP_UTF8);
    fprintf(stderr, "нијe\n");
}
操作系统为Windows 10(1903),在命令提示符下运行,命令行如下:

> for %i in (850 1252 65001) do ( mode con cp select=%i & console.exe & mode con /status )
它生成以下输出(德语区域设置,抱歉):


请注意:如果您想使用
stderr
的句柄,请使用
STD\u ERROR\u HANDLE
而不是
STD\u OUTPUT\u HANDLE

对windows api了解不多,但似乎您正在设置与winapi“stdout”等效的句柄。您仍然在编写“stderr”。无论是stdout还是stderr,您的代码都不应该假定该文件是控制台屏幕缓冲区。您应该检测屏幕缓冲区并调整处理文件的方式。控制台通常使用UTF-8,尤其是在Windows 8之前。C
FILE
streams通过缓冲流,偶尔在两次写入中拆分UTF-8序列,使情况变得更糟,控制台不支持任何版本的Windows。通常我建议使用宽字符函数,如
wprintf
,并将控制台类型文件设置为UTF-16模式,将所有其他类型文件设置为UTF-8模式,例如
\u setmode(\u file(stderr),\u O\u U16TEXT)
。但是,我不知道MinGW使用的旧系统CRT(msvcrt.dll)是否支持在UTF-16模式下切换到控制台的宽字符API。我认为这仅限于较新版本的VC++。如果是这种情况,那么对于控制台I/O,我建议完全直接使用控制台API放弃C标准I/O,即
WriteConsoleW
ReadConsoleW
这在技术上是正确的,因为通常stdout和stderr可能引用不同的文件。(默认情况下,它们引用相同的控制台屏幕缓冲区。)但是,这与问题无关。OP仅使用句柄修改屏幕缓冲区的字体。这与将“呃”(U+043D)写入屏幕的方式无关��", i、 e.两个替换字符(U+FFFD)。
> gcc -Wall -Wextra -pedantic console.c -o console.exe
> for %i in (850 1252 65001) do ( mode con cp select=%i & console.exe & mode con /status )
> (mode con cp select=850   & console.exe   & mode con /status  )

Status von Gerät CON:
---------------------
    Zeilen:          9999
    Spalten:         120
    Wiederholrate:   31
    Verzögerungszeit:1
    Codepage:        850

ð¢ð©Ðÿe
нијe

Status von Gerät CON:
---------------------
    Zeilen:          9999
    Spalten:         120
    Wiederholrate:   31
    Verzögerungszeit:1
    Codepage:        850

> (mode con cp select=1252   & console.exe   & mode con /status  )

Status von Gerät CON:
---------------------
    Zeilen:          9999
    Spalten:         120
    Wiederholrate:   31
    Verzögerungszeit:1
    Codepage:        1252

нијe
нијe

Status von Gerät CON:
---------------------
    Zeilen:          9999
    Spalten:         120
    Wiederholrate:   31
    Verzögerungszeit:1
    Codepage:        1252

> (mode con cp select=65001   & console.exe   & mode con /status  )

Status von Gerät CON:
---------------------
    Zeilen:          9999
    Spalten:         120
    Wiederholrate:   31
    Verzögerungszeit:1
    Codepage:        65001

нијe
нијe

Status von Gerät CON:
---------------------
    Zeilen:          9999
    Spalten:         120
    Wiederholrate:   31
    Verzögerungszeit:1
    Codepage:        65001