C++ Coder

HCP高性能计算架构,实现,编译器指令优化,算法优化, LLVM CLANG OpenCL CUDA OpenACC C++AMP OpenMP MPI

C++博客 首页 新随笔 联系 聚合 管理
  98 Posts :: 0 Stories :: 0 Comments :: 0 Trackbacks

Visual Studio 2008控制台程序无法输出中文!?解决方法只需要设置一下区域即可。没有设置区域前如下图:

Visual Studio 2008控制台程序无法输出中文 - 有何不可 - 不要辜负 期望

包含头文件:#include <locale.h>

函数:_tsetlocale(LC_ALL, _T("chs"));

设置区域后如下图:

Visual Studio 2008控制台程序无法输出中文 - 有何不可 - 不要辜负 期望

参考,摘自微软MSDN

控制台中的编码程序员在对控制台或“文本模式”应用程序编程时可同时使用 Unicode 和 SBCS 或 DBCS 编码。出于承袭方面的考虑,非 Unicode 控制台 I/O 函数使用控制台代码页(默认为 OEM 代码页)。Windows 中的所有其他非 Unicode 函数都使用 Windows 代码页。这意味着其他函数可能无法正确地处理由控制台函数返回的字符串,反之亦然。例如,如果 FindFirstFileA 返回了一个包含某个非 ASCII 字符的字符串,WriteConsoleA 将无法正常地显示该字符串。

要一直跟踪哪些函数需要哪些编码并正确转换文本参数的编码非常困难。函数 SetFileApisToOEM、SetFileApisToANSI 和帮助程序函数 AreFileApisANSI 的引入极大地简化了此项工作。前两个函数可接受或返回文件名称,对 KERNEL32.dll 导出的非 Unicode 函数有效果。顾名思义,SetFileApisToOEM 将这些函数设置为接受或返回与当前系统区域设置对应的 OEM 字符集中的文件名称,而 SetFileApisToANSI 用于为这些名称恢复默认值(Windows ANSI 编码)。使用 AreFileApisANSI 可查询到当前选定的编码。

利用 SetFileApisToOEM 可轻松地解决 WindFirstFileA(或 GetCurrentDirectoryA,或 Win32 API 的任何文件处理函数)的结果无法直接传送给 WriteConsoleA 这一问题:在调用 SetFileApisToOEM 后,WindFirstFileA 将返回以 OEM(而不是以 Windows ANSI 字符集)编码的文本。但此解决方案并非应对所有 Windows ANSI 与 OEM 不兼容情况的万能良方。设想您需要从某个文件处理函数中获取文本,然后将其输出到控制台,接着用其他函数(不受SetFileApisToOEM 的影响)处理该文本。这种绝对理想的情况需要更改编码。否则,您将需要调用 SetFileApisToOEM 以获取用于控制台输出的数据,然后调用SetFileApisToANSI 得到同一文本(使用另一种编码)进行内部处理。另一种 SetFileApisToOEM 无法发挥作用的情况对命令行参数的处理:当您的应用程序的入口点为 main(而不是 wmain)时,参数始终作为 Windows ANSI 字符串数组进行传递。这一切显然使编写非 Unicode 控制台应用程序的程序员的工作变得更复杂了。

更为复杂的是为控制台编写的 8 位代码需要处理两种不同类型的区域设置。在编写代码时,您可以使用 Win32 API 或 C 运行时库函数。Win32 API 的 ANSI 函数假定文本是针对当前控制台代码页(系统区域设置默认定义的)编码的。SetConsoleCP 和 SetConsoleOutputCP 函数可更改这些操作中使用的代码页。用户可在命令提示符下调用 chcp or mode con cp select= 命令,这将会更改当前控制台的代码页。设置固定的控制台代码页的另一种方法是用默认的代码页集创建控制台快捷方式(仅适用于东亚本地化版本的操作系统)。 应用程序应能够响应用户的操作。

C 运行时库(CRT 函数)中区分区域设置函数可依照 (_w)setlocale 调用所定义的设置处理文本。如果代码中未调用 (_w)setlocale,则 CRT 函数对这些操作使用 ANSI "C" 语言不变区域设置,这样就丢失了特定于语言的功能。

该函数的声明为:

setlocale( int category, const char *locale)或

_wsetlocale( int category, const wchar_t *locale)其中 "category" 用于定义受影响的特定于区域的设置(如果指定了 LC_ALL,则全部定义)。可变区域设置可以是显式区域设置名称或下面的某一项:

".OCP" 指与当前用户区域设置对应的 OEM 代码页
".ACP" 或 "" 指与当前用户区域设置对应的 Windows 代码页
".OCP" 和 ".ACP" 参数始终引用用户区域设置(而不是系统区域设置)的设置值。因此不能将它们用于设置 LC_CTYPE。此 "category" 定义了 Unicode 向 8 位转换的规则和其他文本处理程序,必须遵循控制台的设置(可使用 GetConsoleCP 和 GetConsoleOutputCP 访问)。

对控制台应用程序最佳的长期解决方案是使用 Unicode,因为 Unicode 接口是针对 Win32 API 和 C 运行时库定义的。今后的编程模型仍需要您显式地设置区域设置,但至少可肯定通过 Win32 和 CRT 看到的文本不再需要进行代码转换。
posted on 2012-11-03 11:09 jackdong 阅读(1181) 评论(0)  编辑 收藏 引用 所属分类: C/C++Windows编程

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理