C/C++中的字符串问题在网上的讲解一向非常含糊,存在各个层次的库混用、滥用的情况,尤其是宽字符与窄字符等问题很难找到有效的资料,本篇随笔分享一下我长期收集到的一些比较准确的资料以及据此得到的个人理解.
C语言中的字符串
C语言中提供了两种字符类型char和wchar_t,C语言使用字符数组来表示字符串,同时支持两种直接量写法:"abcd"和 L"abcd" 来表示字符串常量文字量,C语言允许用字符串常量来初始化字符串。标准C函数库提供了printf和wprintf两个版本的输出函数。
#include <stdio.h><br>int main(){ <br> char str[] = "abcd"; <br> wchar_t wstr[] = L"abcd数学"; <br> printf("%s/n",str); <br> wprintf(L"%s/n",wstr); <br> return 0; <br>}</stdio.h>
纯C语言环境下,可以使用两个函数wcstombs和mbstowcs 来进行宽窄字符串的互相转换,下面一段是C语言中wcstombs的例子
#include <stdio.h><br>#include <stdlib.h><br>int main(){ <br> char str[] = "abcd"; <br> wchar_t wstr[] = L"bcda"; <br> wcstombs(str,wstr,sizeof(str)); <br> printf("%s/n",str); <br> return 0; <br>}</stdlib.h></stdio.h>
这两个函数都声明在C标准库头文件stdlib.h中。其它配套的字符串操作都在头文件string.h和wchar.h
C++语言中的字符串
C++中我们有了字符串类string和wstring,这两个类都在头文件string当中,并且iostream中也提供了各自对应版本的输出流:
#include <string><br>#include <iostream><br>int main(){ <br> std::string str = "abcd"; <br> std::wstring wstr = L"abcd"; <br> std::cout std::wcout return 0; <br>} <br></iostream></string> C++中转换就很容易了,构造字符串的时候把另一个的迭代器传入就可以了:
#include <string><br>#include <iostream><br>int main(){ <br> std::string str = "abcd"; <br> std::wstring wstr(str.begin(),str.end()); <br> std::wcout return 0; <br>}</iostream></string>
对于已经存在的字符串,可以用assign来赋值。因为宽字符有些窄字符中没有的字符,所以当你要指定一些转换规则时,可以使用头文件algorithm中的transform函数。其它字符串相关操作也在头文件string的类定义当中。
Win32编程中的字符串
COM中提供了一个BSTR类型,它是OLECHAR的字符串形式(OLECHAR可能是WCHAR或者CHAR,取决于系统的OLE字符集),很多人因为看了它的宏定义:
typedef /* [wire_marshal] */ OLECHAR *BSTR;
认为它只是简单的OLECHAR *甚至WCHAR*,但是并非如此。BSTR所指向的内存地址前几个字节也是被分配的空间,用于存储BSTR的长度等信息。所以BSTR对应着一整套相关操作函数:
SysAllocString
SysAllocStringByteLen
SysAllocStringLen
SysFreeString
SysReAllocString
SysReAllocStringLen
SysStringByteLen
SysStringLen
如果你在自己分配的WCHAR*上使用这些函数,一定会导致问题。同样道理,如果你试图用delete去释放BSTR,也会造成错误。但是有相当一部分针对WCHAR的Win32API可以用在BSTR上。