C++ 字符串操作初析
曾经有一篇关于C++程序写作的文章,文章说C++程序员要花费20%的时间来处理字符串方面的细节问题,甚至更多。可见C++中的字符处理是相当复杂,原因是C++中有着丰富的字符及字符串类,如STL中的string,wstring,char,wchar_t、还有windows C程序写作中PTSTR,PWSTR,PTSTR,MFC及ATL中的CString, BSTR,_bstr_t,CComBSTR,OLESTR,还有一种随编译时是否预定义了UNICODE而被分析为具体类型的TCHAR及这些字符,或封装类的一大把函数。而我们要用的系统函数,标准库函数或其它库函数。有的要这种字符而没有提供接受其它字符的版本。这些原因也就促使了C++程序员往往要花许多的时间来处理字符串。上次和朋友聊到写代码的话题。他说一天只能写三百来行的代码。确实要写高效的,高质量的C++代码很要下一番功夫。
在上面介绍了许多的字符串,及字符串封装类。实际上所有的这些类都最终可归结为C风格字符串,也就是字符数组。目前字符的编码方案主要有单字节字符(ANSI)编码,多字节字符(MBCS)编码,还有就是UNICODE编码。前两种字符编码的字符还都是用char这个数据类型来维护。当是多字节时典型的就是2个字节时,就会用2个char来存储,一个字节时就会用一个char来存储。这就是串中的字符占多少个字节得看具体的字符,不能像原来一样一个一个地数就可以知道会占多少个字节。UNICODE则简化了这种编码方案,让每个字符都占用相同大小的字节,UNICODE 中的字符是用wchar_t来定义的,这中编码方案则是每个字符都占用两个字节。在这种编码方案下我们又可以一个一个地数来算出占用了多少字节,计算机可以用一种统计方式来处理这种字符串了。虽然牺牲了些内存,但换取了逻辑的简单性。
这里我写了几个工具函数,可以方便地在各种数据类型之间进行转换。我认为这几个函数会对处理字符串提供帮助,所在我就在首页发表了。大家有什么好的想法可以回复我。另我这两天会封装MSXML来操作XML,希望大家能给点意见。到时我可以与相关参与的人员共享这个封装。
1/**//**//**///////////////////////////////////////////////////////////////////////////
2// Module: stringutility.h
3// Conversion among wchar_t, char and TCHAR
4//
5/**//**//**///////////////////////////////////////////////////////////////////////////
6#ifndef _STRINGUTILITY_H_
7#define _STRINGUTILITY_H_
8
9/**//**//**///////////////////////////////////////////////////////////////////////////
10// get PSTR by PWSTR
11// This function malloc some memory and you must free it
12inline char* newPSTRFromPWSTRT(PWSTR source)
13{
14 char *pCh = NULL;
15 int nLength = 0;
16 if(!source)
17 {
18 pCh = new char[1];
19 }
20 else
21 {
22 nLength= wcslen(source);
23 pCh = new char[2 * nLength + 1];
24 WideCharToMultiByte(CP_ACP,
25 0,
26 source,
27 -1,
28 pCh,
29 nLength * 2,
30 NULL,
31 NULL);
32 }
33 pCh[2 * nLength] = '\0';
34 return pCh;
35}
36
37/**//**//**///////////////////////////////////////////////////////////////////////////
38// get PWSTR by PSTR
39// This function malloc some memory and you must free it
40inline wchar_t* newPWSTRFromPSTR(PSTR source)
41{
42 wchar_t *pCh = NULL;
43 int nLength = 0;
44 if(!source)
45 {
46 pCh = new wchar_t[1];
47 }
48 else
49 {
50 nLength = strlen(source);
51 pCh = new wchar_t[nLength + 1];
52 MultiByteToWideChar(CP_ACP,
53 0,
54 source,
55 -1,
56 pCh,
57 nLength);
58 }
59 pCh[nLength] = '\0';
60 return pCh;
61}
62
63/**//**//**///////////////////////////////////////////////////////////////////////////
64// get PSTR by PTSTR
65// This function malloc some memory and you must free it
66
67inline char* newPSTRFromPTSTR(PTSTR source)
68{
69#ifdef UNICODE
70 return newPSTRFromPWSTRT(source);
71#else
72 char* pCh;
73 int iLength = 0;
74 if(!source)
75 {
76 pCh = new char[1];
77 }
78 else
79 {
80 iLength = strlen(source);
81 pCh = new char[iLength +1];
82 strcpy(pCh, source);
83 }
84 pCh[iLength] = '\0';
85 return pCh;
86#endif
87}
88
89/**//**//**///////////////////////////////////////////////////////////////////////////
90// get PWSTR by PTSTR
91// This function malloc some memory and you must free it
92
93inline wchar_t* newPWSTRFromPTSTR(PTSTR source)
94{
95#ifdef UNICODE
96 wchar_t *pCh = NULL;
97 int nLength = 0;
98 if(!source)
99 {
100 pCh = new wchar_t[1];
101 }
102 else
103 {
104 nLength = wcslen(source);
105 pCh = new wchar_t[nLength + 1];
106 wcscpy(pCh, source);
107 }
108 pCh[nLength] = L'\0';
109 return pCh;
110#else
111 return newPWSTRFromPTSTR(source);
112#endif
113}
114
115
116/**//**//**///////////////////////////////////////////////////////////////////////////
117// get PTSTR by PSTR
118// This function malloc some memory and you must free it
119inline TCHAR* newPTSTRFromPSTR(PSTR source)
120{
121#ifdef UNICODE
122 return newPWSTRFromPSTR(source);
123#else
124 return newPSTRFromPTSTR(source);
125#endif
126}
127
128/**//**//**///////////////////////////////////////////////////////////////////////////
129// get PTSTR by PWSTR
130// This function malloc some memory and you must free it
131inline TCHAR* newPTSTRFromPWSTR(PWSTR source)
132{
133#ifdef UNICODE
134 return newPWSTRFromPTSTR(source);
135#else
136 return newPSTRFromPWSTRT(source);
137#endif
138}
139#endif // end of #ifndef _STRINGUTILITY_H_
在上面介绍了许多的字符串,及字符串封装类。实际上所有的这些类都最终可归结为C风格字符串,也就是字符数组。目前字符的编码方案主要有单字节字符(ANSI)编码,多字节字符(MBCS)编码,还有就是UNICODE编码。前两种字符编码的字符还都是用char这个数据类型来维护。当是多字节时典型的就是2个字节时,就会用2个char来存储,一个字节时就会用一个char来存储。这就是串中的字符占多少个字节得看具体的字符,不能像原来一样一个一个地数就可以知道会占多少个字节。UNICODE则简化了这种编码方案,让每个字符都占用相同大小的字节,UNICODE 中的字符是用wchar_t来定义的,这中编码方案则是每个字符都占用两个字节。在这种编码方案下我们又可以一个一个地数来算出占用了多少字节,计算机可以用一种统计方式来处理这种字符串了。虽然牺牲了些内存,但换取了逻辑的简单性。
这里我写了几个工具函数,可以方便地在各种数据类型之间进行转换。我认为这几个函数会对处理字符串提供帮助,所在我就在首页发表了。大家有什么好的想法可以回复我。另我这两天会封装MSXML来操作XML,希望大家能给点意见。到时我可以与相关参与的人员共享这个封装。
1/**//**//**///////////////////////////////////////////////////////////////////////////
2// Module: stringutility.h
3// Conversion among wchar_t, char and TCHAR
4//
5/**//**//**///////////////////////////////////////////////////////////////////////////
6#ifndef _STRINGUTILITY_H_
7#define _STRINGUTILITY_H_
8
9/**//**//**///////////////////////////////////////////////////////////////////////////
10// get PSTR by PWSTR
11// This function malloc some memory and you must free it
12inline char* newPSTRFromPWSTRT(PWSTR source)
13{
14 char *pCh = NULL;
15 int nLength = 0;
16 if(!source)
17 {
18 pCh = new char[1];
19 }
20 else
21 {
22 nLength= wcslen(source);
23 pCh = new char[2 * nLength + 1];
24 WideCharToMultiByte(CP_ACP,
25 0,
26 source,
27 -1,
28 pCh,
29 nLength * 2,
30 NULL,
31 NULL);
32 }
33 pCh[2 * nLength] = '\0';
34 return pCh;
35}
36
37/**//**//**///////////////////////////////////////////////////////////////////////////
38// get PWSTR by PSTR
39// This function malloc some memory and you must free it
40inline wchar_t* newPWSTRFromPSTR(PSTR source)
41{
42 wchar_t *pCh = NULL;
43 int nLength = 0;
44 if(!source)
45 {
46 pCh = new wchar_t[1];
47 }
48 else
49 {
50 nLength = strlen(source);
51 pCh = new wchar_t[nLength + 1];
52 MultiByteToWideChar(CP_ACP,
53 0,
54 source,
55 -1,
56 pCh,
57 nLength);
58 }
59 pCh[nLength] = '\0';
60 return pCh;
61}
62
63/**//**//**///////////////////////////////////////////////////////////////////////////
64// get PSTR by PTSTR
65// This function malloc some memory and you must free it
66
67inline char* newPSTRFromPTSTR(PTSTR source)
68{
69#ifdef UNICODE
70 return newPSTRFromPWSTRT(source);
71#else
72 char* pCh;
73 int iLength = 0;
74 if(!source)
75 {
76 pCh = new char[1];
77 }
78 else
79 {
80 iLength = strlen(source);
81 pCh = new char[iLength +1];
82 strcpy(pCh, source);
83 }
84 pCh[iLength] = '\0';
85 return pCh;
86#endif
87}
88
89/**//**//**///////////////////////////////////////////////////////////////////////////
90// get PWSTR by PTSTR
91// This function malloc some memory and you must free it
92
93inline wchar_t* newPWSTRFromPTSTR(PTSTR source)
94{
95#ifdef UNICODE
96 wchar_t *pCh = NULL;
97 int nLength = 0;
98 if(!source)
99 {
100 pCh = new wchar_t[1];
101 }
102 else
103 {
104 nLength = wcslen(source);
105 pCh = new wchar_t[nLength + 1];
106 wcscpy(pCh, source);
107 }
108 pCh[nLength] = L'\0';
109 return pCh;
110#else
111 return newPWSTRFromPTSTR(source);
112#endif
113}
114
115
116/**//**//**///////////////////////////////////////////////////////////////////////////
117// get PTSTR by PSTR
118// This function malloc some memory and you must free it
119inline TCHAR* newPTSTRFromPSTR(PSTR source)
120{
121#ifdef UNICODE
122 return newPWSTRFromPSTR(source);
123#else
124 return newPSTRFromPTSTR(source);
125#endif
126}
127
128/**//**//**///////////////////////////////////////////////////////////////////////////
129// get PTSTR by PWSTR
130// This function malloc some memory and you must free it
131inline TCHAR* newPTSTRFromPWSTR(PWSTR source)
132{
133#ifdef UNICODE
134 return newPWSTRFromPTSTR(source);
135#else
136 return newPSTRFromPWSTRT(source);
137#endif
138}
139#endif // end of #ifndef _STRINGUTILITY_H_