You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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系统。


问题原因与解决方案

核心原因

  1. 输入流未配置为宽字符模式:仅将标准输出(stdout)设置为_O_U16TEXT(UTF-16宽字符模式),但标准输入(stdin)仍保持默认的ANSI字节流模式。wscanf读取时会将ANSI编码的字符转宽字符,而å在ANSI编码(如Windows-1252)中的值与UTF-16的0x00E5不匹配,导致读取后编码错误,打印出乱码。
  2. 混用字节流与宽字符流输出:代码混用printf(字节流输出)和wprintf(宽字符流输出),而stdout已设为宽字符模式,这种混用会破坏输出字节序列,加剧显示异常。

修复步骤

  1. 为stdin设置宽字符模式:在set_locale_mode函数的MSVC分支中,添加输入流模式设置:
    _setmode(_fileno(stdin), _O_U16TEXT);
    
  2. 统一使用宽字符输出函数:将printf("Now, enter 3 characters: ");替换为wprintf(L"Now, enter 3 characters: ");,确保输出流一致性。
  3. (可选)确认控制台代码页:运行程序前执行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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 10:17:41