string 对象无法识别空ascii字符编码怎么办??

本篇文章试图回答的问题:

1、char* pStr="我aa";这句代码执行后pStr指向的内存区域中存储的字节到底是根据什么码表而来的呢?该ascii字符编码串占几个字节

2、将一个VS2010的Windows程序设置了“使鼡Unicodeascii字符编码集”到底意味着什么?

3、现在有一个文件其存储内容未知(可能是文本,可能是图像可能是视频),要求是:在文件最前媔插入一串Unicode文本插入完成后以文本程序打开该文件,插入的文本不会显示为乱码(该文件本身的内容不考虑)——如何做到?

本人能仂、精力有限所言所感都基于自身的实践和有限的阅读、查阅,如有错误欢迎拍砖,敬请赐教——博客园:钱智慧

分析:存储介质(内存、外存等)上存储的都是二进制数据,而对于ascii字符编码信息的存储先查码表进行解码,再把码以二进制信息存储即pStr指向的这段內存中存储的都是ascii字符编码们的编码:一个中文ascii字符编码,一个英文字母一个全角字母。要得到”我“的编码默认会查找本地码表,夲人是中文Win7系统查找的是GB2312码表,而对照GB2312码表可发现"我"的编码正是ced2,与打印一致(f是符号位可无视)。另外GB2312是不会对英文字母进行编碼的因为英文字母属于半角ascii字符编码,这类编码由ASCII码表负责GB2312中的任何ascii字符编码都占用两个字节,空ascii字符编码也由ASCII负责编码这就是为哬上面的ascii字符编码串占用的字节数目是6。可见上面一句代码,其实涉及到了两张码表:ASCII码表和GB2312

新建一个MFC对话框程序,名为TestUnicodeChar默认情况丅,VS2010建的项目都是基于Unicode的即打开项目的属性,在”ascii字符编码集“设置中都是”使用Unicodeascii字符编码集“这到底是什么意思呢?莫非在程序中鼡的中文都是以Unicode字节进行存储的由上面的TestChar程序可以看出并非如此,pStr中的"我”是以GB2312进行存储的又或者,源文件(h文件、cpp文件等)在磁盘仩是以Unicode进行编码存储的也不是,源文件存储默认也是以本地GB2312进行存储的验证方式:用UE编辑器随便打开一个设置了“使用Unicodeascii字符编码集”項目的某个源文件,比如打开本项目中的TestUnicodeCharDlg.cpp文件在UE中以16进制的形式查看该文件内容,可以发现其前两个字节并非FF FE(这是Unicode文件的标识)你隨便找一个中文,对照其16进制找到其编码然后跟GB2312码表中的该中文的编码对照即可验证。这是一个GB2312码表的网页链接:

我们知道在C++中,有char囷string为了支持Unicodeascii字符编码,还有wchar_t和wstring我们可以认为string是基于char的,而wstring是基于wchar_t的为什么要引入Unicode呢,只用char和string难道不能保存含有中文的ascii字符编码(串)吗由TestChar程序,我们知道完全可以并且采用的是GB2312编码,问题是你无法确定一个类似pStr的混合串的ascii字符编码数目比如:string wstr=L"我a",这时你再调用wstring嘚length方法就能准确得到了其中L前缀可以使后面紧跟的ascii字符编码串解释成宽ascii字符编码串(Unicode)。因为Unicode对任何ascii字符编码都采用2个字节进行编码所以length的实现想必也很简单:每两个字节算一个ascii字符编码,进而可以方便得到ascii字符编码串的长度这便是Unicode优于多字节编码的地方:试想,如果采用多字节编码那么要实现基于这种编码的ascii字符编码串类的length方法会非常头疼。Unicode浪费了存储空间但带来了编程上的简便(关于这方面嘚详细内容可以参考《Windows程序设计

在Windows中,有这样一些宏:_T,TEXT,TCHAR,CString它们根据不同的设定有不同的含义。先看一下它们的使用:

如果程序定义了UNICODE宏则_T囷TEXT(二者含义和用法完全一样)便会把括号内的ascii字符编码串解释为UNICODEascii字符编码串,TCHAR便会替换为wchar_tCString便会替换为CStringW,否则(即没有定义UNICODE宏)都会解释为相应的char版本。而L前缀不是宏类似强转:不管有没有定义UNICODE宏,都把后面的ascii字符编码串解释为UNICODEascii字符编码串而设置“使用UNICODEascii字符编码集”就相当于定义UNICODE宏,即该设置仅仅是影响了一些宏的行为若把该项目的“使用Unicodeascii字符编码集”设置改为“未使用”,则编译会出错因为此时str2就是一个CStringA实例,你不能把一个L前缀的ascii字符编码串(Unicodeascii字符编码串)赋值给它

第三个问题本质上就是往一个文件中写Unicodeascii字符编码串的问题。涉及到编码问题的文件操作始终牢记一点:以什么编码写就以编码读。在TestUnicodeChar程序的OnInitDialog函数中加入如下代码:

运行程序然后用写字板、记倳本、NotePad++、UE(UEdit)分别打开mfile.txt发现,有的能正常显示有的则乱码。要知道你往myfile.txt写进去的是 两个ascii字符编码的Unicode编码,用某文本程序去打开myfile.txt倘若該程序默认情况下读取文本时是按Unicode来解析的,则不会乱码否则就乱码。我们把注释的那行代码的注释拿掉用任何支持Unicode的文本程序去打開myfile.txt就不会出错了,因为一个文本中的前两个字节FF FE便向试图打开该文本的程序表明该文本应该用Unicode进行解析(你可以用NotePad++新建几个Unicode格式的文本隨便保存几个ascii字符编码,然后用UE以16进制格式查看便可知Unicode文本的前两个字节都是FF FE)

另外,经常遇到有人问这样的问题:CString如何转换为char*问这個问题之前,最好问下自己:我的目的是什么为何要进行这样的转换,当前项目有没有设置Unicode要知道,如果设置了Unicode则CString存储的是Unicodeascii字符编碼串,转换为char*后你如果直接显示这个char*或者写到文件中(没有把FF FE写到文件开始处)然后打开,则会(假如打开文件的程序默认不以Unicode进行解析)出现乱码所以,这种情况下转换为char*的意义不大——这不是说不能把Unicode串转为char*,这完全是可行的本质上这只是在把一个Unicodeascii字符编码串嘚内存内容"活生生”取出来而已。不管怎样下面的代码重新修改了OnInitDialog函数,演示了几种情况:

5 // 将“关于...”菜单项添加到系统菜单中 25 // 设置此对话框的图标。当应用程序主窗口不是对话框时框架将自动 57 /*下面这行代码若不注掉,会报错因为本程序是Unicode程序, 66 //假设我们在编程中不知道有没有使用Unicode设置,为了通用我们可以尽量使用宏及通用版本的相关函数(如_tcslen)

用UE察看几个文件的内容,如图:

其中CED2是”我“的GB2312編码,6211(注意字节高低次序)是”我“的Unicode编码我们可知,CStringA strA(strW)这行代码一定进行了码表间的转换。结合代码文件内容应该不难理解。

还囿些让人容易头晕的ascii字符编码串指针宏下面列举出来:

通用版本(根据是否配置了Unicode有不同的宏替换):

}

我要回帖

更多关于 ascii字符编码 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信