zoukankan      html  css  js  c++  java
  • 字符串表示与转换

        windows 编程中,存在几种字符串表示方式,包括:

        1)C-Style 字符串 char* / wchar_t*;

        2)C++ STL 字符串 std::string / std::wstring;

        3)  ATL/MFC 字符串 CStringA / CStringW;

        以上每个版本都有对应的多字节(MBCS)与Unicode(DBCS)表示,其中多字节存在不同编码方案,使用代码页区分。在 windows 系统中,常见代码页有:

        1)MS-DOS Latin US, code page 437,使用一个八位字节表示拉丁字符;

        2)windows code page 1251 for Cyrillic, 使用一个八位字节表示斯拉夫字符;

        3)code page 936/950/932/949 for ideographic,分别表示 简体中文/繁体中文/日语/韩语,使用一个八位字符表示拉丁字符,使用两个八位字符表示象形文字;

        针对象形文字,使用 strlen 函数求字符串长度是没有意义的,strlen 函数简单返回字符串中以 '' 结尾前字符个数。

        Unicode 使用两个字节表示一个字符,前128位与 ASCII(American Standard Code for Information Interchange) 保持一致。在使用非象形文字时语言时,有一半空间被浪费,故基于 Unicode 字符进行在编码,形成 utf8。这样,针对拉丁语系,斯拉夫语系等仅需要一个字符表示 Unicode 编码,而象形文字使用2,3,4个字节编码,具体见博客  ”字符集及编码“。在 visual c++开发中,utf8 编码可看作一种特殊代码页,使用函数 WideCharToMultiByte(CP_UTF8,...) 可以得到。

        

        如何维护在一个源文件中维护两种编码方案(MBCS & UNICODE)?

        winows 系统如下定义:

     1 typedef wchar_t WCHAR;    // wc,   16-bit UNICODE character
     2 
     3 #ifdef  UNICODE   
     4 // PTCHAR is a pointer to WCHAR 
     5 typedef WCHAR TCHAR, *PTCHAR;
     6 #else
     7 // PTCHAR is a pointer to char
     8 typedef char TCHAR, *PTCHAR;
     9 #endif 
    10 
    11 #ifdef  _UNICODE
    12 #define _tcscpy        wcscpy
    13 #define _tcslen         wcslen
    14 ...
    15 #else
    16 #define _tcscpy     strcpy
    17 #define _tcslen     strlen
    18 ...
    19 #endif
    20 
    21 #ifdef  _UNICODE
    22 #define __T(x)      L ## x
    23 #define __TEXT(quote) L##quote 
    24 #else
    25 #define __T(x)      x
    26 #define __TEXT(quote) quote
    27 #endif
    28 
    29 // _T(x) __T(x) TEXT(x) _TEXT(x) __TEXT(x) same meaning
    30 #define _T(x)       __T(x)
    31 #define _TEXT(x)    __T(x)
    32 #define TEXT(quote) __TEXT(quote)

        根据以上定义,可以在使用一个源文件维护 C-Style 字符串,具体如下:

    1 TCHAR *sz = _T("ch中国");
    2 int iLen = _tcslen(sz);
    3 TCHAR *sz2 = new TCHAR[iLen + 1];
    4 _tcscpy(sz2, sz);
    5 delete []sz2;

        在项目 Properties->Configuration Prooperties->General 下选择 Use Multi-Byte Character Set(or Not Set ),iLen 值为 6,其中每个汉字使用两个字节;当选择 Use Unicode Character Set 时,iLen 值为 4, 表示 sz 有 4 个字符。

        C++ STL 字符串 与 ATL/MFC 字符串是对 TCHAR 字符数据进行封装,表示如下:

     1 // c++ string
     2 typedef basic_string<char, char_traits<char>, allocator<char> >
     3     string;
     4 typedef basic_string<wchar_t, char_traits<wchar_t>,
     5     allocator<wchar_t> > wstring;
     6 
     7 // atl/mfc string
     8 typedef ATL::CStringT< wchar_t, StrTraitMFC_DLL< wchar_t > > CStringW;
     9 typedef ATL::CStringT< char, StrTraitMFC_DLL< char > > CStringA;
    10 typedef ATL::CStringT< TCHAR, StrTraitMFC_DLL< TCHAR > > CString;
    11 
    12 // 由于c++ string 没有提供一个 TCHAR 版本,通过增加如下定义,
    13 // 实现多字节与Unicode自动转换
    14 #ifdef _UNICODE
    15 #define tstring std::wstring
    16 #else
    17 #define tstring std::string
    18 #endif

        通过以上定义,使用 tstring(自定义),CString 可以在一个源文件中维护两种类型字符串。windows 也允许使用特定字符集字符串,提供了 MBCS/Unicode 之间转换函数,具体如下:

     1 // char* -> wchar_t*
     2 //char *sz1 = "ch中国";
     3 // 获取 sz1 字符串转换为 Unicode 长度
     4 int iLen = MultiByteToWideChar(CP_ACP, 0, sz1, strlen(sz1), NULL, 0);
     5 wchar_t* sz2 = new wchar_t[iLen + 1];
     6 MultiByteToWideChar(CP_ACP, 0, sz1, strlen(sz1), sz2, iLen);
     7 sz2[iLen] = '';  // 以 '' 结尾字符串
     8 
     9 // wchar_t* -> char*
    10 wchar_t* sz3 = L"ch中国";
    11 // 获取 sz3 字符串转换为 多字节 长度
    12 int iLen2 = WideCharToMultiByte(CP_ACP, 0, sz3, wcslen(sz3), NULL, 0, NULL, NULL);
    13 char *sz4 = new char[iLen2 + 1];
    14 WideCharToMultiByte(CP_ACP, 0, sz3, wcslen(sz3), sz4, iLen2, NULL, NULL);
    15 sz4[iLen2] = ''; // 可不使用 L 标志,因为单个字符系统可以零补齐
    16 
    17 // CStringA -> CStringW
    18 CStringA szA("ch中国");
    19 CStringW szW(szA);
    20 
    21 // CStringW -> CStringA
    22 CStringW szW2(L"ch中国");
    23 CStringA szA2(szW2);
    24 
    25 
    26 // unicode -> utf8 -> Unicode
    27 // vs 默认使用 CP_ACP 翻译多字节,当需要查看 utf8 编码字符串时,可在 watch 窗口添加 ,s8 查看
    28 wchar_t *szUtf16 =  L"ch中国";
    29 int len = WideCharToMultiByte(CP_UTF8, 0, szUtf16, wcslen(szUtf16), NULL, 0, NULL, NULL);
    30 char *szUtf8 = new char[len + 1];
    31 WideCharToMultiByte(CP_UTF8, 0, szUtf16, wcslen(szUtf16), szUtf8, len, NULL, NULL);
    32 szUtf8[len] = '';
    33 int len2 = MultiByteToWideChar(CP_UTF8, 0, szUtf8, strlen(szUtf8), NULL, 0);
    34 wchar_t *szUtf16_2 = new wchar_t[len2 + 1];
    35 MultiByteToWideChar(CP_UTF8, 0, szUtf8, strlen(szUtf8), szUtf16_2, len2);
    36 szUtf16_2[len2] = '';

        编程过程中经常使用不同类型字符串,如何在不同类型字符串见转换呢?代码如下:

     1 // TCHAR* <-> CString
     2 TCHAR *sz = _T("ch中国");
     3 CString cstr(sz);
     4 TCHAR* sz2 = cstr.GetBuffer();
     5 
     6 // TCHAR* <-> tsring
     7 tstring tstr(sz);
     8 const TCHAR* sz3 = tstr.c_str();  // tstr.data() is also ok
     9 
    10 // CString <-> tstring
    11 CString cstr2;
    12 tstring tstr2;
    13 tstr2 = cstr.GetBuffer();
    14 cstr2 = tstr.c_str();
  • 相关阅读:
    五个问题,三大策略,手把手教你定制App性能监控方案
    Oracle外部表详解 转
    EBS 一揽子采购协议 转载
    xsl特殊符号输出总结 转
    设计模式目录
    控制CPU使用率,让它画一条弧线
    C# 俄罗斯方块
    程序员能力矩阵
    如何在IIS上搭建WAP网站
    利用SQL2005的row_number()重新写了个自定义分页存储过程
  • 原文地址:https://www.cnblogs.com/luofeiju/p/12501873.html
Copyright © 2011-2022 走看看