Windows下使用wscanf处理宽字符时å显示异常的问题
问题:wscanf读取含å的字符后无法正确打印(Windows系统)
我尝试输入3个包含å的字符,测试代码如下:
#ifdef _MSC_VER #include <io.h> // _setmode #include <fcntl.h> // _O_U16TEXT #endif #include <stdio.h> #include <locale.h> #include <wchar.h> #define SIZE 4 void set_locale_mode() { #ifdef _MSC_VER // Unicode UTF-16, little endian byte order (BMP of ISO 10646) const char *CP_UTF_16LE = ".1200"; setlocale(LC_ALL, CP_UTF_16LE); _setmode(_fileno(stdout), _O_U16TEXT); #else setlocale(LC_ALL, ""); #endif } int main(void) { set_locale_mode(); wchar_t myString[SIZE]; wchar_t testChar=0x00E5; wprintf(L"Your test character is %lc\n", testChar); printf("Now, enter 3 characters: "); wscanf(L"%ls", myString); wprintf(L"Your input is %ls\n", myString); return 0; }
输入blå后得到如下输出:
Your test character is å Now, enter 3 characters: blå Your input is bl┼
为何使用wscanf后å无法正确打印?我使用的是Windows系统。
问题原因与解决方案
核心原因
- 输入流未配置为宽字符模式:仅将标准输出(stdout)设置为
_O_U16TEXT(UTF-16宽字符模式),但标准输入(stdin)仍保持默认的ANSI字节流模式。wscanf读取时会将ANSI编码的字符转宽字符,而å在ANSI编码(如Windows-1252)中的值与UTF-16的0x00E5不匹配,导致读取后编码错误,打印出乱码。 - 混用字节流与宽字符流输出:代码混用
printf(字节流输出)和wprintf(宽字符流输出),而stdout已设为宽字符模式,这种混用会破坏输出字节序列,加剧显示异常。
修复步骤
- 为stdin设置宽字符模式:在
set_locale_mode函数的MSVC分支中,添加输入流模式设置:_setmode(_fileno(stdin), _O_U16TEXT); - 统一使用宽字符输出函数:将
printf("Now, enter 3 characters: ");替换为wprintf(L"Now, enter 3 characters: ");,确保输出流一致性。 - (可选)确认控制台代码页:运行程序前执行
chcp 65001切换到UTF-8代码页,或chcp 1200切换到UTF-16代码页,避免控制台编码冲突。
修改后的完整代码
#ifdef _MSC_VER #include <io.h> // _setmode #include <fcntl.h> // _O_U16TEXT #endif #include <stdio.h> #include <locale.h> #include <wchar.h> #define SIZE 4 void set_locale_mode() { #ifdef _MSC_VER // Unicode UTF-16, little endian byte order (BMP of ISO 10646) const char *CP_UTF_16LE = ".1200"; setlocale(LC_ALL, CP_UTF_16LE); _setmode(_fileno(stdout), _O_U16TEXT); _setmode(_fileno(stdin), _O_U16TEXT); // 添加输入流模式设置 #else setlocale(LC_ALL, ""); #endif } int main(void) { set_locale_mode(); wchar_t myString[SIZE]; wchar_t testChar=0x00E5; wprintf(L"Your test character is %lc\n", testChar); wprintf(L"Now, enter 3 characters: "); // 统一用宽字符输出 wscanf(L"%ls", myString); wprintf(L"Your input is %ls\n", myString); return 0; }
修改后重新运行,输入blå即可正常输出Your input is blå。
内容的提问来源于stack exchange,提问作者Alexander Jonsson
相关产品推荐
相关产品推荐

