VC++ 字符串操作學習總結


vc++中各種字符串(轉載)

http://www.cnblogs.com/tomin/archive/2008/12/28/1364097.html


CString ,BSTR ,LPCTSTR之間關系和區別


CString是一個動態TCHAR數組,BSTR是一種專有格式的字符串(需要用系統提供的函數來操縱,LPCTSTR只是一個常


量的TCHAR指針。


CString 是一個完全獨立的類,動態的TCHAR數組,封裝了 + 等操作符和字符串操作方法。
typedef OLECHAR FAR* BSTR;
typedef const char * LPCTSTR;


vc++中各種字符串的表示法


首先char* 是指向ANSI字符數組的指針,其中每個字符占據8位(有效數據是除掉最高位的其他7位),這里保持了與傳


統的C,C++的兼容。


LP的含義是長指針(long pointer)。LPSTR是一個指向以‘\0’結尾的ANSI字符數組的指針,與char*可以互換使用,在


win32中較多地使用LPSTR。
而LPCSTR中增加的‘C’的含義是“CONSTANT”(常量),表明這種數據類型的實例不能被使用它的API函數改變,


除此之外,它與LPSTR是等同的。
1.LP表示長指針,在win16下有長指針(LP)和短指針(P)的區別,而在win32下是沒有區別的,都是32位.所以這里的LP和P是等


價的.
2.C表示const
3.T是什么東西呢,我們知道TCHAR在采用Unicode方式編譯時是wchar_t,在普通時編譯成char.


為了滿足程序代碼國際化的需要,業界推出了Unicode標准,它提供了一種簡單和一致的表達字符串的方法,所有字符


中的字節都是16位的值,其數量也可以滿足差不多世界上所有書面語言字符的編碼需求,開發程序時使用Unicode(類


型為wchar_t)是一種被鼓勵的做法。


LPWSTR與LPCWSTR由此產生,它們的含義類似於LPSTR與LPCSTR,只是字符數據是16位的wchar_t而不是char。


然后為了實現兩種編碼的通用,提出了TCHAR的定義:
如果定義_UNICODE,聲明如下:
typedef wchar_t TCHAR;
如果沒有定義_UNICODE,則聲明如下:
typedef char TCHAR;


LPTSTR和LPCTSTR中的含義就是每個字符是這樣的TCHAR。


CString類中的字符就是被聲明為TCHAR類型的,它提供了一個封裝好的類供用戶方便地使用。


LPCTSTR:
        #ifdef _UNICODE
           typedef const wchar_t * LPCTSTR;
        #else
           typedef const char * LPCTSTR;
        #endif


VC常用數據類型使用轉換詳解


先定義一些常見類型變量借以說明
int i = 100;
long l = 2001;
float f=300.2;
double d=12345.119;
char username[]="女俠程佩君";
char temp[200];
char *buf;
CString str;
_variant_t v1;
_bstr_t v2;


一、其它數據類型轉換為字符串


短整型(int)
          itoa(i,temp,10);        //將i轉換為字符串放入temp中,最后一個數字表示十進制
          itoa(i,temp,2);         //按二進制方式轉換 
長整型(long)
          ltoa(l,temp,10);


二、從其它包含字符串的變量中獲取指向該字符串的指針


CString變量
str = "2008北京奧運";
buf = (LPSTR)(LPCTSTR)str; 
BSTR類型的_variant_t變量
v1 = (_bstr_t)"程序員";
buf = _com_util::ConvertBSTRToString((_bstr_t)v1);


三、字符串轉換為其它數據類型
strcpy(temp,"123"); 


短整型(int)
         i = atoi(temp); 
長整型(long)
         l = atol(temp); 
浮點(double)
         d = atof(temp);


四、其它數據類型轉換到CString


使用CString的成員函數Format來轉換,例如:


整數(int)
         str.Format("%d",i); 
浮點數(float)
         str.Format("%f",i); 
字符串指針(char *)等已經被CString構造函數支持的數據類型可以直接賦值
         str = username;


五、BSTR、_bstr_t與CComBSTR


CComBSTR、_bstr_t是對BSTR的封裝,BSTR是指向字符串的32位指針。
char *轉換到BSTR可以這樣: BSTR b=_com_util::ConvertStringToBSTR("數據");        //使用前需要加上頭文件


comutil.h
反之可以使用char *p=_com_util::ConvertBSTRToString(b);


六、VARIANT 、_variant_t 與 COleVariant


VARIANT的結構可以參考頭文件VC98\Include\OAIDL.H中關於結構體tagVARIANT的定義。
對於VARIANT變量的賦值:首先給vt成員賦值,指明數據類型,再對聯合結構中相同數據類型的變量賦值,舉個例子:
VARIANT va;
int a=2001;
va.vt=VT_I4;       //指明整型數據
va.lVal=a;         //賦值


對於不馬上賦值的VARIANT,最好先用Void VariantInit(VARIANTARG FAR* pvarg);進行初始化,其本質是將vt設置為


VT_EMPTY,下表我們列舉vt與常用數據的對應關系:


unsigned char bVal; VT_UI1 
short iVal; VT_I2 
long lVal;     VT_I4  
float fltVal;     VT_R4 
double dblVal;     VT_R8  
VARIANT_BOOL boolVal;     VT_BOOL 
SCODE scode;     VT_ERROR 
CY cyVal;     VT_CY 
DATE date;     VT_DATE 
BSTR bstrVal;     VT_BSTR 
IUnknown FAR* punkVal;     VT_UNKNOWN 
IDispatch FAR* pdispVal;     VT_DISPATCH 
SAFEARRAY FAR* parray;     VT_ARRAY|* 
unsigned char FAR* pbVal;     VT_BYREF|VT_UI1 
short FAR* piVal;     VT_BYREF|VT_I2 
long FAR* plVal;     VT_BYREF|VT_I4 
float FAR* pfltVal;     VT_BYREF|VT_R4 
double FAR* pdblVal; VT_BYREF|VT_R8 
VARIANT_BOOL FAR* pboolVal; VT_BYREF|VT_BOOL 
SCODE FAR* pscode;     VT_BYREF|VT_ERROR 
CY FAR* pcyVal;     VT_BYREF|VT_CY 
DATE FAR* pdate; VT_BYREF|VT_DATE 
BSTR FAR* pbstrVal;     VT_BYREF|VT_BSTR 
IUnknown FAR* FAR* ppunkVal;     VT_BYREF|VT_UNKNOWN 
IDispatch FAR* FAR* ppdispVal; VT_BYREF|VT_DISPATCH 
SAFEARRAY FAR* FAR* pparray;     VT_ARRAY|* 
VARIANT FAR* pvarVal;     VT_BYREF|VT_VARIANT 
void FAR* byref;     VT_BYREF 


_variant_t是VARIANT的封裝類,其賦值可以使用強制類型轉換,其構造函數會自動處理這些數據類型。
例如:
long l=222;
ing i=100;
_variant_t lVal(l);
lVal = (long)i;


COleVariant的使用與_variant_t的方法基本一樣,請參考如下例子:
COleVariant v3 = "字符串", v4 = (long)1999;
CString str =(BSTR)v3.pbstrVal;
long i = v4.lVal;


七、其它


對消息的處理中我們經常需要將WPARAM或LPARAM等32位數據(DWORD)分解成兩個16位數據(WORD),例如:
LPARAM lParam;
WORD loValue = LOWORD(lParam);        //取低16位
WORD hiValue = HIWORD(lParam);        //取高16位 
對於16位的數據(WORD)我們可以用同樣的方法分解成高低兩個8位數據(BYTE),例如:
WORD wValue;
BYTE loValue = LOBYTE(wValue);        //取低8位
BYTE hiValue = HIBYTE(wValue);        //取高8位 


如何將CString類型的變量賦給char*類型的變量
1、GetBuffer函數:
使用CString::GetBuffer函數。
char *p; 
CString str="hello"; 
p=str.GetBuffer(str.GetLength()); 
str.ReleaseBuffer();


將CString轉換成char * 時
CString str("aaaaaaa");
strcpy(str.GetBuffer(10),"aa");
str.ReleaseBuffer();
當我們需要字符數組時調用GetBuffer(int n),其中n為我們需要的字符數組的長度.使用完成后一定要馬上調用


ReleaseBuffer();
還有很重要的一點就是,在能使用const char *的地方,就不要使用char *


2、memcpy: 
CString mCS=_T("cxl"); 
char mch[20]; 
memcpy(mch,mCS,20); 


3、用LPCTSTR強制轉換: 盡量不使用
char *ch; 
CString str; 
ch=(LPSTR)(LPCTSTR)str; 


CString str = "good";
char *tmp;
sprintf(tmp,"%s",(LPTSTR)(LPCTSTR)str); 


4、
CString Msg; 
Msg=Msg+"abc"; 
LPTSTR lpsz; 
lpsz = new TCHAR[Msg.GetLength()+1]; 
_tcscpy(lpsz, Msg); 
char * psz; 
strcpy(psz,lpsz); 


CString類向const char *轉換
char a[100];
CString str("aaaaaa");
strncpy(a,(LPCTSTR)str,sizeof(a));
或者如下:
strncpy(a,str,sizeof(a));
以上兩種用法都是正確地. 因為strncpy的第二個參數類型為const char *.所以編譯器會自動將CString類轉換成const 


char *.


CString轉LPCTSTR (const char *)
CString cStr;
const char *lpctStr=(LPCTSTR)cStr;


LPCTSTR轉CString
LPCTSTR lpctStr;
CString cStr=lpctStr;


將char*類型的變量賦給CString型的變量
可以直接賦值,如: 
CString myString = "This is a test"; 
也可以利用構造函數,如: 
CString s1("Tom");


將CString類型的變量賦給char []類型(字符串)的變量
1、sprintf()函數
CString str = "good";
char tmp[200] ;
sprintf(tmp, "%s",(LPCSTR)str);  
(LPCSTR)str這種強制轉換相當於(LPTSTR)(LPCTSTR)str 
CString類的變量需要轉換為(char*)的時,使用(LPTSTR)(LPCTSTR)str 


然而,LPCTSTR是const char *,也就是說,得到的字符串是不可寫的!將其強制轉換成LPTSTR去掉const,是極為危險


的!
一不留神就會完蛋!要得到char *,應該用GetBuffer()或GetBufferSetLength(),用完后再調用ReleaseBuffer()。


2、strcpy()函數
CString str;
char c[256];
strcpy(c, str); 


char mychar[1024];
CString source="Hello";
strcpy((char*)&mychar,(LPCTSTR)source); 


關於CString的使用
1、指定 CString 形參
       對於大多數需要字符串參數的函數,最好將函數原型中的形參指定為一個指向字符 (LPCTSTR) 而非 CString 的 


const 指針。
當將形參指定為指向字符的 const 指針時,可將指針傳遞到 TCHAR 數組(如字符串 ["hi there"])或傳遞到 CString 


對象。
CString 對象將自動轉換成 LPCTSTR。任何能夠使用 LPCTSTR 的地方也能夠使用 CString 對象。


2、如果某個形參將不會被修改,則也將該參數指定為常數字符串引用(即 const CString&)。如果函數要修改該字符


串,
則刪除 const 修飾符。如果需要默認為空值,則將其初始化為空字符串 [""],如下所示:
void AddCustomer( const CString& name, const CString& address, const CString& comment = "" ); 


3、對於大多數函數結果,按值返回 CString 對象即可。


串的基本運算
       對於串的基本運算,很多高級語言均提供了相應的運算符或標准的庫函數來實現。
為敘述方便,先定義幾個相關的變量:
       char s1[20]="dir/bin/appl",s2[20]="file.asm",s3[30],*p;
       int result;
       下面以C語言中串運算介紹串的基本運算 
1、求串長
           int strlen(char *s);            //求串s的長度
       【例】printf("%d",strlen(s1));       //輸出s1的串長12


2、串復制
       char *strcpy(char *to,*from);//將from串復制到to串中,並返回to開始處指針
       【例】strcpy(s3,s1);     //s3="dir/bin/appl",s1串不變


3、聯接
       char *strcat(char *to,char *from);//將from串復制到to串的末尾,
                                         //並返回to串開始處的指針
       【例】strcat(s3,"/");       //s3="dir/bin/appl/"
            strcat(s3,s2);        //s3="dir/bin/appl/file.asm"


4、串比較
       int strcmp(char *s1,char *s2);//比較s1和s2的大小,
        //當s1<s2、s1>s2和s1=s2時,分別返回小於0、大於0和等於0的值 
       【例】result=strcmp("baker","Baker");       //result>0
               result=strcmp("12","12");          //result=0
               result=strcmp("Joe","joseph")      //result<0


5、字符定位
       char *strchr(char *s,char c);//找c在字符串s中第一次出現的位置,
                                    //若找到,則返回該位置,否則返回NULL
       【例】p=strchr(s2,'.');         //p指向"file"之后的位置
     if(p) strcpy(p,".cpp");        //s2="file.cpp" 


     注意:
        ①上述操作是最基本的,其中后 4個操作還有變種形式:strncpy,strncath和strnchr。
        ②其它的串操作見C的<string.h>。在不同的高級語言中,對串運算的種類及符號都不盡相同
        ③其余的串操作一般可由這些基本操作組合而成


       【例】求子串的操作可如下實現:
       void substr(char *sub,char *s,int pos,int len){
            //s和sub是字符數組,用sub返回串s的第pos個字符起長度為len的子串
            //其中0<=pos<=strlen(s)-1,且數組sub至少可容納len+1個字符。
           if (pos<0||pos>strlen(s)-1||len<0)
               Error("parameter error!");
           strncpy(sub,&s[pos],len);         //從s[pos]起復制至多len個字符到sub
========

vc++中各種字符串的表示法

http://blog.csdn.net/kybd2006/article/details/1566827


        首先char* 是指向ANSI字符數組的指針,其中每個字符占據8位(有效數據是除掉最高位的其他7位);


        LP的含義是長指針(long pointer)。LPSTR是一個指向以‘/0’結尾的ANSI字符數組的指針,與char*可以互換使


用,在win32中較多地使用LPSTR(並且長指針(LP)和短指針(P)是等價的)。而LPCSTR中增加的‘C’的含義


是“CONSTANT”(常量),表明這種數據類型的實例不能被使用它的API函數改變,除此之外,它與LPSTR是等同的





        我們知道TCHAR在采用Unicode方式編譯時是wchar_t,在普通時編譯成char,業界推出的Unicode標准,它提供


了一種簡單和一致的表達字符串的方法,所有字符中的字節都是16位的值,其數量也可以滿足差不多世界上所有書面語


言字符的編碼需求,開發程序時使用Unicode(類型為wchar_t)是一種被鼓勵的做法。LPWSTR與LPCWSTR由此產生,


它們的含義類似於LPSTR與LPCSTR,只是字符數據是16位的wchar_t而不是char。


        然后為了實現兩種編碼的通用,提出了TCHAR的定義:
       如果定義_UNICODE,聲明如下:
               typedef wchar_t TCHAR;
       如果沒有定義_UNICODE,則聲明如下:
               typedef char TCHAR;
       LPTSTR和LPCTSTR中的含義就是每個字符是這樣的TCHAR。
      CString類中的字符就是被聲明為TCHAR類型的,它提供了一個封裝好的類供用戶方便地使用。




     LPCTSTR:
     #ifdef _UNICODE
        typedef const wchar_t * LPCTSTR;
     #else
        typedef const char * LPCTSTR;
     #endif
========

vc++下的字符串處理

http://blog.chinaunix.net/uid-192452-id-3182259.html
07年在啟明做個專題的講座,現在提煉升華一下。
vc工程中考慮到UNICODE的設置問題,盡可能使用三種字符串,ATL的CString,不是mfc的CString,使用com 就使用


CComBSTR,使用api的話,盡可能用TCHAR,字符串操作盡可能用_tcs函數。
除非考慮跨平台,否則不要使用stl的string,應該使用CString,雖然可以使用如下設置
#include 
using namespace std;
#ifndef UNICODE
typedef string TSTRING;
#else
typedef wstring TSTRING;
#endif
使用stl的string 以后的字符串操作會很復雜,
例如得到程序當前的路徑
TCHAR buffer[MAX_PATH+1];
DWORD iNombreChars = GetCurrentDirectory(MAX_PATH, buffer);
string strPath;
strPath.assign(&buffer[0], &buffer[iNombreChars]);
這是閑的蛋疼
也有簡單的,
std::string str(MAX_PATH+1, 0);
GetCurrentDirectory(MAX_PATH, &str[0]);
將string轉為TCHAR
TCHAR *param=new TCHAR[tsDir.size()+1];
param[tsDir.size()]=_T('\0');
//As much as we'd love to, we can't use memcpy() because
//sizeof(TCHAR)==sizeof(char) may not be true:
std::copy(tsDir.begin(),tsDir.end(),param);
如果經常轉換,最后會抓狂的。
========

返璞歸真vc++之字符類型

http://www.cnblogs.com/lichaoxyz/p/3636906.html
  在今天,大量使用java與.net的程序員已經很少去真實了解字符的底層表達,但是使用VC++編程,對字符的處理卻


非常慎重,剛學習vc++肯定會為其中的字符類型給暈頭轉向,今天本人學習第一節,從字符開始


  特別說明:本文章所有開發環境選用vs2012開發


  在計算機系統中所有的數據與程序指令都是二進制的形式存在的,CPU處理器給特定序列的二進制序列包含有特殊


的意義,及我們常說的計算機指令,計算機指令目前流行的X86指令集,以及目前流行android平台下arm指令集,同時


所有的數據也是以二進制的形式表達在計算機中,主要表達在計算機體系中的內存,寄存器,以及CPU緩存。所以計算


機認識到的字符也就是一串二進制格式的數據,計算機的首要任務就是給這些二進制進行字符的映射,但是在不同的指


令集與CPU下,對這些二進制進行翻譯的過程中又產生了高位與低位只說,這個只是CPU級別的二進制讀取順序,如何


給這些特定的二進制翻譯成我們熟悉的人類語言,於是就產生了我們經常所說的字符串編碼,常用的有ASCII編碼,以及


Unicode,


  asccii編碼,及單個字節編碼,1個字節8個位,也就是說,在計算機內存中,8個連續的位能代碼一個字符,那么如


何映射成字符呢,那么就是通過我們的assicc表來實現,如下


八進制 十六進制 十進制 字符 八進制 十六進制 十進制 字符
00 00 0 nul 100 40 64 @
01 01 1 soh 101 41 65 A
02 02 2 stx 102 42 66 B
03 03 3 etx 103 43 67 C
04 04 4 eot 104 44 68 D
05 05 5 enq 105 45 69 E
06 06 6 ack 106 46 70 F
07 07 7 bel 107 47 71 G
10 08 8 bs 110 48 72 H
11 09 9 ht 111 49 73 I
12 0a 10 nl 112 4a 74 J
13 0b 11 vt 113 4b 75 K
14 0c 12 ff 114 4c 76 L
15 0d 13 cr 115 4d 77 M
16 0e 14 so 116 4e 78 N
17 0f 15 si 117 4f 79 O
20 10 16 dle 120 50 80 P
21 11 17 dc1 121 51 81 Q
22 12 18 dc2 122 52 82 R
23 13 19 dc3 123 53 83 S
24 14 20 dc4 124 54 84 T
25 15 21 nak 125 55 85 U
26 16 22 syn 126 56 86 V
27 17 23 etb 127 57 87 W
30 18 24 can 130 58 88 X
31 19 25 em 131 59 89 Y
32 1a 26 sub 132 5a 90 Z
33 1b 27 esc 133 5b 91 [
34 1c 28 fs 134 5c 92 \
35 1d 29 gs 135 5d 93 ]
36 1e 30 re 136 5e 94 ^
37 1f 31 us 137 5f 95 _
40 20 32 sp 140 60 96 '
41 21 33 ! 141 61 97 a
42 22 34 " 142 62 98 b
43 23 35 # 143 63 99 c
44 24 36 $ 144 64 100 d
45 25 37 % 145 65 101 e
46 26 38 & 146 66 102 f
47 27 39 ` 147 67 103 g
50 28 40 ( 150 68 104 h
51 29 41 ) 151 69 105 i
52 2a 42 * 152 6a 106 j
53 2b 43 + 153 6b 107 k
54 2c 44 , 154 6c 108 l
55 2d 45 - 155 6d 109 m
56 2e 46 . 156 6e 110 n
57 2f 47 / 157 6f 111 o
60 30 48 0 160 70 112 p
61 31 49 1 161 71 113 q
62 32 50 2 162 72 114 r
63 33 51 3 163 73 115 s
64 34 52 4 164 74 116 t
65 35 53 5 165 75 117 u
66 36 54 6 166 76 118 v
67 37 55 7 167 77 119 w
70 38 56 8 170 78 120 x
71 39 57 9 171 79 121 y
72 3a 58 : 172 7a 122 z
73 3b 59 ; 173 7b 123 {
74 3c 60 < 174 7c 124 |
75 3d 61 = 175 7d 125 }
76 3e 62 > 176 7e 126 ~
77 3f 63 ? 177 7f 127 del
其中,每一個二進制序列對應這一個英文與數字字符,例如常說的十進制數65的二進制表達是1000001,對應的十六進制


為0x41;


我們都知道c語言中,字符是用char類型表示,同時默認的編碼格式為asccii編碼,也就是說當0x41這個十六進制數在轉


換成整形值是65,在進行asccii字符轉換時,如上表所示,即我們常說的大寫字母A,


下面我們做一個實驗,即可證明以上觀點是否正確


#include "stdafx.h"


int _tmain(int argc, _TCHAR* argv[])
{
    //數值數據
    int i=0x41;
    //內存數據按整形值翻譯打印出來
    printf("this is int%d\n",i);
    //內存數據按照asccii翻譯打印出來
    printf("this is char%c\n",i);
    //打印出內存數據的十六進制格式
    printf("this is binary 0x%x\n",i);
    return 0;
}
復制代碼
打印結果如下


由此可見,數據的表達都是二進制,只是人為的定義了一些一些含義,你認為是字符的時候,就轉換成字符,你認為是


數字的時候就變成了數字,你認為是指令的時候,就編程了是指令,只是指令已經被CPU確定了含義。


那么同理得出Unicode也是類似的結構,只是有點不同


1、Unicode為雙字節編碼,也就是說一個字符需要兩個字節的容量才能保存


所以需要特別注意的地方到了,那么以上這些函數printf能處理Unicode字符串嗎?


答案顯然是不能的,我們依然寫一個程序去驗證我們的結果


#include "stdafx.h"
#include <Windows.h>


int _tmain(int argc, _TCHAR* argv[])
{
    WCHAR unicodeChar='很';
    printf("this is unicode Char%c\n",unicodeChar);


    return 0;
}


 打印的結論:


可以看到,最終被一個問號代替了,也就是說,printf函數並沒有把他解析出來,它依然按照asccii標准去解析,所以變


成了問號,那么疑問出來了


WCHAR到底是一個什么類型呢,怎么在c++標准中並不存在這樣一個類型呢?


答案馬上揭曉,我們找到了下面的宏定義


#ifndef _MAC //非蘋果硬件平台
typedef wchar_t WCHAR;  //實際值是wchar_t  // wc,   16-bit UNICODE character
#else
// some Macintosh compilers don't define wchar_t in a convenient location, or define it as a char
typedef unsigned short WCHAR; //蘋果硬件平台實際上是unsigned short
// wc, 16-bit UNICODE character #endif


 也就是如上所述:


所以在我們常用的電腦下,都是wchar_t類型,那么這又是一個什么類型呢?


百度百科給出的定義如下,http://baike.baidu.com/link?


url=s9f5p8uJEuzVarbu0ilC2XTNRSEQHmxMM0pAHJE5w-Iysq2KFAmRXQUqSuYbbIF-AwmC0e_-


Rtsy9NUKP6QVYK


char是8位字符類型,最多只能包含256種字符,許多外文字符集所含的字符數目超過256個,char型無法表示。
wchar_t數據類型一般為16位或32位,但不同的C或C++庫有不同的規定,如GNU Libc規定wchar_t為32位[1],總之,


wchar_t所能表示的字符數遠超char型。
標准C++中的wprintf()函數以及iostream類庫中的類和對象能提供wchar_t寬字符類型的相關操作。
所以是一個寬字符,也就是比char類型大,支持多種語言,比如東南亞國家的語言等,所以我認為在后續的編程中,應


該盡可能的使用寬字符類型,同時對於寬字符類型,c++標准也提供了wprintf一系列類來操作
今天就是以上學習的內容啦,大概就這么多了,通過理解原理,然后去看vc++對這些類型的宏包裝,其中不同類型的相


互轉換應該也是有所理解的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM