`
daojin
  • 浏览: 677354 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

wprintf 和 wcout

阅读更多

wprintf 和 wcout

这篇文章应该是[netsin]的成果,我勤快,记下来。
注:wprintf是C的标准库函数,但wcout不是C++的标准成员,C++中的 L"……" 是宽字符,却未必是unicode字符,这与编译器实现相关。
[乾坤一笑]说:为什么 C/C++ 语言把 L"xx" 定义为由实现决定的呢?这显然是为了 C/C++ 的普适性、可移植性。Bjarne 的观点认为,C++ 的方式是允许程序员使用任何字符集作为串的字符类型。另外,unicode 编码已经发展了若干版本了,是否能永久适合下去也不得而知。有关 unicode 的详细论述以及和其它字符集的比较,我推荐你看《无废话xml》。


以下两段代码的执行环境是 windows xp professional 英文版,编译器是 VS2005RTM。

// C
#include <stdio.h>
#include <locale.h>
int main( void )
{
    setlocale( LC_ALL, "chs" );
    //setlocale( LC_ALL, "Chinese-simplified" );
    //setlocale( LC_ALL, "ZHI" );
    //setlocale( LC_ALL, ".936" );
    wprintf( L"中国" );

    return 0;
}

// C++
#include <iostream>
#include <locale>
using namespace std;
int main( void )
{
    locale loc( "chs" );
    //locale loc( "Chinese-simplified" );
    //locale loc( "ZHI" );
    //locale loc( ".936" );
    wcout.imbue( loc );
    std::wcout << L"中国" << endl;

    return 0;
}

说明:别混合使用 setlocale 和 std::locale 。

------------------------- 2006-07-05 记 -------------------------

 "VC知识库"                        编码为:56 43 D6 AA CA B6 BF E2 00                            // ANSI编码
L"VC知识库" 在VC++               中编码为:56 00 43 00 E5 77 C6 8B 93 5E 00 00                   // (windows口中的unicode)编码
L"VC知识库" 在GCC(Dev-CPP4990) 中编码为:56 00 43 00 D6 00 AA 00 CA 00 B6 00 BF 00 E2 00 00 00 // 只是将ANSI编码简单的加0
L"VC知识库" 在GCC(Dev-CPP4992) 中编译失败,报 Illegal byte sequence

L"VC知识库" 在 Dev-CPP4992 中解决步骤为:
a. 将文件保存为 utf-8 编码                                          // utf-8 是unicode的其中一种,但和(windows口中的unicode)不一样
b. 去掉BOM头:用二进制编辑器(比如VC)去掉刚才utf-8文件的前三个字节 // Linux/UNIX并不使用BOM
c. 使用 gcc/g++ 编译运行

经过以上解决步骤,在 dev-cpp4992 中
 "VC知识库" 编码为: 56 43 E7 9F A5 E8 AF 86 E5 BA 93 00 // utf-8编码,注意不再是ANSI编码了,因此用 printf/cout 将输出乱码
L"VC知识库" 编码为: 56 00 43 00 E5 77 C6 8B 93 5E 00 00 // (windows口中的unicode)编码

补充:在mingw32中使用wcout和wstring需要加一些宏,比如
#define _GLIBCXX_USE_WCHAR_T 1
#include <iostream>
int main( void )
{
    std::wcout << 1 << std::endl;
}
可以编译通过,但无法Link通过,在网上google了一下,stlport说mingw32有问题,mingw32说是M$的c runtime有问题。

------------------------- 2007-01-05 记 -------------------------
一个多字节字符串和宽字符字符串互相转化的事例
#define _CRT_SECURE_NO_WARNINGS // only for vc8
#include <string>
#include <clocale>
#include <cassert>
inline const std::string to_mbcs( const std::string& src )
{
    return src;
}
const std::string to_mbcs( const std::wstring& src )
{
    char* old_locale = _strdup( setlocale(LC_CTYPE,NULL) ); // 保存原来的locale
    setlocale( LC_CTYPE, "chs" ); // 设置当前locale为chs,这在非简体中文平台上不可缺少

    size_t count1 = wcstombs( NULL, src.c_str(), 0 ); // 计算新字符串长度
    std::string des( count1, ' ' );
    size_t count2 = wcstombs( &des[0], src.c_str(), count1 ); // 转化
    assert( count1 == count2 );

    setlocale( LC_CTYPE, old_locale ); // 恢复到原来的locale
    free( old_locale );

    return des;
}
inline const std::wstring to_wcs( const std::wstring& src )
{
    return src;
}
const std::wstring to_wcs( const std::string& src )
{
    char* old_locale = _strdup( setlocale(LC_CTYPE,NULL) ); // 保存原来的locale
    setlocale( LC_CTYPE, "chs" ); // 设置当前locale为chs,这在非简体中文平台上不可缺少

    size_t count1 = mbstowcs( NULL, src.c_str(), 0 ); // 计算新字符串长度
    std::wstring des( count1, L' ' );
    size_t count2 = mbstowcs( &des[0], src.c_str(), count1 ); // 转化
    assert( count1 == count2 );

    setlocale( LC_CTYPE, old_locale ); // 恢复到原来的locale
    free( old_locale );

    return des;
}

#include <iostream>
int main( void )
{
    using namespace std;

    cout << to_mbcs("你好1") << endl;
    cout << to_mbcs(L"你好2") << endl;

    const locale loc( "chs" );
    wcout.imbue( loc );
    wcout << to_wcs("你好3") << endl;
    wcout << to_wcs(L"你好4") << endl;
}

分享到:
评论

相关推荐

    浅谈C中的wprintf和宽字符显示

    浅谈C中的wprintf和宽字符显示 非常值得收藏的一篇文档

    Ansi、Unicode、UTF8字符串之间的转换,wprintf

    Ansi、Unicode、UTF8字符串之间的转换,wprintf

    解析wprintf 中使用%I64d格式化输出LONGLONG的详细介绍

    wprintf 中使用%I64d格式化输出LONGLONG 在写某个程序时,因为需要用到一个大的整数,就是要了LONGLONG型: 代码如下:LONGLONG nLarge;但是格式化时不知道应该用什么字符,用 %d,%l都不行。LONGLONGLONGLONG其实...

    VB API实现简单的程序窗口.rar

    VB 基于API技术实现简单的程序窗口,源码文件说明:用VB的模块模仿写的几个小例子(不用窗体)[源码] ...主要是用到了wsprintf函数,对应于Win32API函数wprintf(Win32API函数wprintf在VB中不能去调用它,调用会出错。)

    qt 通过hid获取指定usb设备 并读取数据

    wprintf(L"Serial Number String: (%d) %s\n", wstr[0], wstr); // Read Indexed String 1 res = hid_get_indexed_string(handle, 1, wstr, MAX_STR); wprintf(L"Indexed String 1: %s\n", wstr); qDebug("hid...

    Code:Blocks-中文乱码问题原因分析和解决方法1

    1.Tiny C 编译没问题,但是wprintf是显示不出内容的 2.VC2005-2010 一切OK,没有乱码 1.Code::Blocks 编辑器保存

    Stingray:IDAPython插件,用于递归查找函数字符串

    黄貂鱼 Stingray是用于查找函数字符串的IDA...}void foo (){wprintf (L " hello from foo \n " );bar ();}void foo2 (){wprintf (L " hello from foo2 \n " );bar ();}void main (){printf ( " hello from main \n " );

    LPK专杀C语言源码

    // 删除路径后面的文件名和’/’符号。该函数可以分析出一个文件的路径。 PathAppend(szTmpRARPath, L"rar.exe"); GetFileAttributes(szTmpRARPath);// 获取到压缩包rar.exe的路径 TCHAR seps[] = L"\""; ...

    EDA/PLD中的C++标准库之中文输出详细介绍

    使用C++标准库的iostream,可以方便地将...关于C语言中的 printf和wprintf的中文输出,本文也进行了探讨。  需要说明的是,我的开发环境是VS 2005(标准库当然也是微软实现的),不保证其它环境下是相同的效果。  1

    C++标准库之中文输出详细介绍

    使用C++标准库的iostream,可以方便地将...关于C语言中的 printf和wprintf的中文输出,本文也进行了探讨。  需要说明的是,我的开发环境是VS 2005(标准库当然也是微软实现的),不保证其它环境下是相同的效果。  1

    Detours Express源码(微软API HOOK库)

    wprintf(L"usage %s pid", argv[0]); return 1; } nProcessId = _wtoi(argv[1]); printf("%d ",nProcessId); ---- /*要成功执行ContinueProcessWithDll,要对winlogon.exe等进程的进程句柄有读写存储器内容和创建...

    detour 2.1

    wprintf(L"usage %s pid", argv[0]); return 1; } nProcessId = _wtoi(argv[1]); printf("%d ",nProcessId); ---- /*要成功执行ContinueProcessWithDll,要对winlogon.exe等进程的进程句柄有读写存储器内容和创建...

    C标准库源代码(学习C/C++必备)

    介绍说明 C标准库源代码,能提高对C的理解,不错的哦 下载文件列表 Pack : clibsource.rar C 标准库源代码\ABORT.C C标准库源代码\ABS.C C标准库源代码\ACCESS.C C标准库源代码\ADJUSTFD.C C标准库源代码\ALGRITHM ...

Global site tag (gtag.js) - Google Analytics