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

C++启用Windows控制台ANSI转义序列后Unicode字符显示异常

问题根因

开启ANSI虚拟终端序列(VTP)时,仅给控制台模式追加了ENABLE_VIRTUAL_TERMINAL_PROCESSING标志,没有同步配置UTF-8输出环境。Windows控制台在传统非VTP模式下对U+2500段制表符有内置兼容映射,开启VTP后会严格按照当前绑定的输出代码页解析字节流:简体中文Windows默认输出代码页为GBK(936),代码中输出的UTF-8编码制表符会被按GBK规则错误解析,最终显示为乱码。

修复步骤

需要补全控制台编码配置,同时保存初始状态用于ANSI禁用后的恢复:

  1. 新增静态变量存储初始控制台输入/输出代码页
  2. 开启VTP时,显式将控制台代码页切换为UTF-8(代码页ID CP_UTF8即65001)
  3. 配置C++标准库全局locale为UTF-8,保证流输出编码和控制台编码对齐
  4. 禁用ANSI时,同步恢复初始控制台模式和初始代码页

修改后的完整my_windows.cpp代码如下:

#ifdef _WIN32
#include <windows.h>
#endif

#include "my_windows.hpp"

#include <iostream>
#include <locale>
#include <stdexcept>

namespace osm
 {
  #ifdef _WIN32
  #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
  #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
  #endif

  static HANDLE stdoutHandle;
  static DWORD outModeInit;
  static DWORD initInCP;
  static DWORD initOutCP;
  #endif
  
  void enableANSI()
   {
    #ifdef _WIN32
    DWORD outMode = 0;
    stdoutHandle = GetStdHandle( STD_OUTPUT_HANDLE );
    
    if( stdoutHandle == INVALID_HANDLE_VALUE )
     {
      exit( GetLastError() );
     }
    
    if( ! GetConsoleMode( stdoutHandle, &outMode ) )
     {
      exit( GetLastError() );
     }
    
    outModeInit = outMode;
    // 保存初始代码页
    initInCP = GetConsoleCP();
    initOutCP = GetConsoleOutputCP();

    // 开启虚拟终端处理,保留原有模式标志
    outMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
    
    if( ! SetConsoleMode( stdoutHandle, outMode ) )
     {
      exit( GetLastError() );
     }

    // 切换控制台代码页为UTF-8
    SetConsoleCP(CP_UTF8);
    SetConsoleOutputCP(CP_UTF8);
    #endif

    // 配置C++标准库使用UTF-8 locale
    std::locale::global(std::locale(".UTF8"));
    std::cout.sync_with_stdio(false);
   }
  
  void disableANSI()
   {
    std::cout << "\033[0m";
  
    #ifdef _WIN32
    // 恢复初始控制台模式
    if( ! SetConsoleMode( stdoutHandle, outModeInit ) )
     {
      exit( GetLastError() );
     }
    // 恢复初始代码页
    SetConsoleCP(initInCP);
    SetConsoleOutputCP(initOutCP);
    #endif
   }
 }
额外注意事项
  • 如果使用MSVC编译器编译项目,需要添加/utf-8编译选项,保证代码中的字符串字面量以UTF-8编码编译进二进制文件,避免字面量本身编码错误
  • 开启ANSI后不要手动切换控制台代码页,也不要混合输出GBK、UTF-8等多种编码的内容,否则会再次出现乱码
  • 确保程序运行在Windows 10 1511及以上版本,旧版Windows系统原生不支持ANSI虚拟终端序列和UTF-8控制台

内容的提问来源于stack exchange,提问作者Gianluca Bianco

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 00:06:14