【MFC】MFC基础类——CString(使用心得)
文章目錄
- 01、CString類介紹
- 02、常見函數(shù)表
- 03、CString類成員函數(shù)示例
- 3.1、CString(構(gòu)造函數(shù))
- 3.2、GetLength
- 3.3、IsEmpty
- 3.4、Empty
- 3.5、GetAt
- 3.6、SetAt
- 3.7、Compare
- 3.8、CompareNoCase
- 3.9、Mid、Right、Left
- 3.10、Find、FindOneOf
- 3.11、MakeUpper、MakeLower、MakeReverse
- 3.12、Replace
- 3.13、Delete、Insert、Remove
- 3.14、Format
- 3.15、GetBuffer、ReleaseBuffer
- 3.16、LoadString
- 04、常見類型轉(zhuǎn)換
- 05、小結(jié)
01、CString類介紹
前言:串操作是編程中最常用也最基本的操作之一。 做為VC程序員,無論是菜鳥或高手都曾用過Cstring。而且好像實(shí)際編程中很難離得開它(雖然它不是標(biāo)準(zhǔn)C++中的庫)。因?yàn)镸FC中提供的這個(gè)類對(duì)我們操作字串實(shí)在太方便了,CString不僅提供各種豐富的操作函數(shù)、操作符重載,使我們使用起串起來更象basic中那樣直觀;而且它還提供了動(dòng)態(tài)內(nèi)存分配,使我們減少了多少字符串?dāng)?shù)組越界的隱患。但是,我們?cè)谑褂眠^程中也體會(huì)到CString簡直太容易出錯(cuò)了,而且有的不可捉摸。所以有許多高人站過來,建議拋棄它。
在此,我個(gè)人認(rèn)為:CString封裝得確實(shí)很完美,它有許多優(yōu)點(diǎn),如“容易使用 ,功能強(qiáng),動(dòng)態(tài)分配內(nèi)存,大量進(jìn)行拷貝時(shí)它很能節(jié)省內(nèi)存資源并且執(zhí)行效率高,與標(biāo)準(zhǔn)C完全兼容,同時(shí)支持多字節(jié)與寬字節(jié),由于有異常機(jī)制所以使用它安全方便” 其實(shí),使用過程中之所以容易出錯(cuò),那是因?yàn)槲覀儗?duì)它了解得還不夠,特別是它的實(shí)現(xiàn)機(jī)制。因?yàn)槲覀冎械拇蠖鄶?shù)人,在工作中并不那么愛深入地去看關(guān)于它的文檔,何況它還是英文的。
CString 是一種很有用的數(shù)據(jù)類型。它們很大程度上簡化了MFC中的許多操作,使得MFC在做字符串操作的時(shí)候方便了很多。不管怎樣,使用CString有很多特殊的技巧,特別是對(duì)于純C背景下走出來的程序員來說有點(diǎn)難以學(xué)習(xí)。這篇文章就來討論這些技巧。
使用CString可以讓你對(duì)字符串的操作更加直截了當(dāng)。這篇文章不是CString的完全手冊(cè),但囊括了大部分常見基本問題。
02、常見函數(shù)表
看不懂沒關(guān)系,下面都會(huì)舉例描述,如有不明確的地方,評(píng)論區(qū)、或者私聊我,知道的一定盡力給你們說明白
| CString | CString類構(gòu)造函數(shù) | 略 |
| GetLength | 返回CString對(duì)象中的字符數(shù) | 對(duì)于多字節(jié)字符,計(jì)算每個(gè)8位字符;也就是說,一個(gè)多字節(jié)字符中的一個(gè)前導(dǎo)字節(jié)和一個(gè)跟蹤字節(jié)被計(jì)算為兩個(gè)字符。 |
| IsEmpty | 測(cè)試CString對(duì)象是否不包含字符 | 為空,返回0;反之,返回非0 |
| Empty | 強(qiáng)制字符串具有0長度 | 強(qiáng)制清空字符串內(nèi)容 |
| GetAt | 返回給定位置的字符 | 參數(shù)應(yīng)避免負(fù)數(shù),否則會(huì)出現(xiàn)意想不到的結(jié)果 |
| SetAt | 在給定的位置設(shè)置字符 | 當(dāng)參數(shù)為負(fù)數(shù)或超出對(duì)象末尾時(shí),會(huì)發(fā)生無法預(yù)料的結(jié)果 |
| Compare | 比較兩個(gè)字符串 | 區(qū)分大小寫 |
| CompareNoCase | 比較兩個(gè)字符串 | 不區(qū)分大小寫 |
| Collate | 比較兩個(gè)字符串 | 區(qū)分大小寫,使用特定于地區(qū)的信息 |
| CollateNoCase | 比較兩個(gè)字符串 | 不區(qū)分大小寫,使用特定于地區(qū)的信息 |
| Mid | 提取字符串的中間部分 | 此函數(shù)于我而言,多用于字符的匹配等功能 |
| Right | 提取字符串的右邊部分 | Right函數(shù)一般來說用于CString的分段或者在正則表達(dá)式中叫字符分割 |
| Left | 提取字符串的左邊部分 | 同上 |
| SpanIncluding | 提取僅包含集合中字符的子字符串 | 于我而言,上面三個(gè)已是足夠 |
| SpanExcluding | 提取僅包含不包含在集合中的字符的子字符串 | 同上,相反的含義 |
| Find | 在母串中查找子串 | 母串:源字符串 子串:查找的字符串 次函數(shù)必須完全匹配子串才ok,不然返回 -1,找到則返回開始下標(biāo) |
| ReverseFind | 反向查找,同上 | 同上 |
| FindOneOf | 從集合中查找第一個(gè)匹配字符 | 此為非完全匹配,找到一個(gè)即停止查找(下面示例慢慢解釋) |
| MakeUpper | 將此字符串中的所有字符轉(zhuǎn)換為大寫字符 | 有則轉(zhuǎn)換,無則什么都不做,用于防呆 |
| MakeLower | 將此字符串中的所有字符轉(zhuǎn)換為小寫字符 | 同上 |
| MakeReverse | 顧名思義,翻轉(zhuǎn)字符串,即從尾至頭的一串新字符 | 熟悉數(shù)據(jù)結(jié)構(gòu)就知道,此函數(shù)為逆轉(zhuǎn)算法中的一部分 |
| Replace | 用其他字符替換指示字符 | 次函數(shù)在字符串操作時(shí)算是高頻函數(shù) |
| Remove | 從字符串中移除指示字符 | 返回值為移除的數(shù)目 |
| Insert | 在字符串中的給定索引處插入單個(gè)字符或子字符串 | 返回插入后對(duì)象的長度 |
| Delete | 從字符串中刪除一個(gè)或多個(gè)字符 | 此處略 |
| Format | 格式化字符串 | 高頻中的高頻函數(shù) |
| FormatV | 將字符串格式化為vsprintf | 我是很少使用次函數(shù) |
| TrimLeft | 從字符串中修剪前導(dǎo)空格字符 | 前導(dǎo)空格:指變量或者常量值的有效內(nèi)容前面的空格 |
| TrimRight | 從字符串中修剪尾隨空格字符 | 略 |
| FormatMessage | 格式化消息字符串 | MFC通常用自帶的消息框 |
| GetBuffer | 返回指向CString中字符的指針 | CString轉(zhuǎn)string字符串時(shí)的中間轉(zhuǎn)換函數(shù) |
| ReleaseBuffer | 釋放GetBuffer返回的緩沖區(qū)的控制 | 略 |
| LockBuffer | 禁用引用計(jì)數(shù)并保護(hù)緩沖區(qū)中的字符串 | 基本用不上,略 |
| UnlockBuffer | 啟用引用計(jì)數(shù),并釋放緩沖區(qū)中的字符串 | 同上 |
| LoadString | 從Windows資源加載現(xiàn)有的CString對(duì)象 | 用于涉及到多國語言,需進(jìn)行語言替換的時(shí)候,資源切換 |
03、CString類成員函數(shù)示例
3.1、CString(構(gòu)造函數(shù))
CString類所需頭文件:#include <afx.h>,下面示例略,僅展示示例核心代碼
//五種方法,以換行分割,請(qǐng)忽略變量名重名。 CString str; //最簡單的無參構(gòu)造CString str("ABCDE"); //帶內(nèi)容的構(gòu)造 CString buf(str); //類的拷貝構(gòu)造 //buf輸出:ABCDECString str("ABCDEFGH",3); //str輸出:ABCCString str('a',5); //str輸出:aaaaawchar_t s[]=L"abcdef"; CString str(s); //str輸出:abcdef/* 或許有人會(huì)問,你全用英文,那中文的呢? OK,他來了,請(qǐng)看*/ CString str = _T("我是小豬"); CString buf(str,4); //buf輸出: 我是 ~~~~~~為啥沒有小豬,因?yàn)樾∝i被我吃了(開玩笑) //因?yàn)?#xff1a;英文我們一般用1個(gè)字節(jié)就夠了,但是中文字符,一個(gè)中文占2個(gè)字節(jié),編譯器不一樣,或許也不一樣,想知道你的是多少,可以用下面要說的GetLength方法查看3.2、GetLength
CString str("AaBbCc"); CString buf = _T("你也是小豬");//因?yàn)镚etLength返回的是int類型,所以我們用int類型接收他的返回值 int nOneCharLen = str.GetLength(); //6 int nOneChinaesLen = buf.GetLength(); //10/* 比如:我們現(xiàn)在想遍歷一串字符串,該怎么做? 現(xiàn)有知識(shí)肯定已經(jīng)是夠了,如下 */ for(int i = 0; i < str.GetLength(); i++) {CString demo;demo = str[i]; //是不是每一個(gè)字符都獲取到了,想看就打印,想保存就存起來 }3.3、IsEmpty
//測(cè)試對(duì)象是否為空,為空時(shí)返回零,不為空時(shí)返回非零 CString str(_T("C++ is a very good language!")); CString buf;if(buf.IsEmpty()) {//非0進(jìn)入 } else {//進(jìn)入此節(jié)點(diǎn) }if(str.IsEmpty()) {//進(jìn)入此節(jié)點(diǎn) } else {//為0才進(jìn)入 }3.4、Empty
//此函數(shù)的意思是將字符串中的內(nèi)容強(qiáng)制清空,例如: CString str = _T("No NULL"); int len = str.GetLength(); //6str.Empty(); //強(qiáng)制清空內(nèi)容int len2 = str.GetLength(); //03.5、GetAt
TCHAR GetAt( int nIndex ) const; //返回下標(biāo)為nIndex的字符,與字符串的[]用法相同CString str(_T("hello,Cain Or Xcy!"));char ch = GetAt(3); //l,看見這個(gè),上面遍歷的時(shí)候,str[i]也可以替換為str.GetAt(i)3.6、SetAt
void SetAt( int nIndex, TCHAR ch ); //給下標(biāo)為nIndex的字符重新賦值//nIndex: 將要重新賦值的下標(biāo) //ch:將要替換的內(nèi)容CString buf(_T(ABCD)); buf.SetAt(2,c); //溫馨提示:編程里面很多都是以0為起始下標(biāo),不清楚的時(shí)候,可以自己輸出測(cè)試一下, //實(shí)際編程的時(shí)候,差之毫厘,失之千里。//重新輸出 AfxMessageBox(buf,MB_ICONINFORMATION); //ABcD3.7、Compare
int Compare( LPCTSTR lpsz ) const; //區(qū)分大小寫比較兩個(gè)字符串,相等時(shí)返回0,大于時(shí)返回1,小于時(shí)返回-1CString str(_T("AAAA")); int bRet = str.Compare(_T("aaaa")); if(bRet == 0) {//相等 } else if(bRet == 1) {//大于,進(jìn)入此節(jié)點(diǎn) } else {//小于 }3.8、CompareNoCase
int CompareNoCase( LPCTSTR lpsz ) const; //不區(qū)分大小寫比較兩個(gè)字符串,相等時(shí)返回0,大于時(shí)返回1,小于時(shí)返回-1CString str(_T("AAAA")); int bRet = str.Compare(_T("aaaa")); if(bRet == 0) {//相等,進(jìn)入此節(jié)點(diǎn) } else if(bRet == 1) {//大于 } else {//小于 }Ps:上面的比較依據(jù)是ASCII碼值。
3.9、Mid、Right、Left
如果,現(xiàn)在讓你取兩個(gè)字符串中的某一段來對(duì)比,他們是不是全等的,兩個(gè)CString完成,那么你就不得不使用下面的三個(gè)函數(shù)。
CString Left( int nCount ) const; //從左取字串 CString Right( int nCount ) const; //從右取字串 CString Mid( int nFirst ) const; CString Mid( int nFirst, int nCount ) const; //從中間開始取字串CString str = _T("Cain"); CString buf = _T("Beck");//首先,演示三個(gè)函數(shù)的效果 CString temp; temp = str.Right(2); //in temp = str.Left(1); //C temp = str.Mid(1); //ain,無第二參數(shù),默認(rèn)從參數(shù)一開始直接取到結(jié)尾//示例(對(duì)比,第5~7位是否相等) CString str = _T("This is example!"); CString buf = _T("Cain want to go home!");CString tmp1,tmp2; tmp1 = str.Mid(5,2); tmp2 = buf.Mid(5,2);if(str.Find(buf) != -1) {//相等,Find函數(shù),下面就會(huì)提及 } else {//不相等 }3.10、Find、FindOneOf
int Find( TCHAR ch ) const; //找字符,默認(rèn)從0開始 int Find( LPCTSTR lpszSub ) const; //找字符串,默認(rèn)從0開始 int Find( TCHAR ch, int nStart ) const; //找字符,從nStart開始 int Find( LPCTSTR pstr, int nStart ) const; // 找字符串,從nStart開始 //查找字串,nStart為開始查找的位置。未找到匹配時(shí)返回-1,否則返回字串的開始位置 int FindOneOf( LPCTSTR lpszCharSet ) const; //查找lpszCharSet中任意一個(gè)字符在CString對(duì)象中的匹配位置。未找到時(shí)返回-1,否則返回字串的開始位置CString str(_T("ABC is enough!")); if(str.Find('e') == -1); //使用形式之一,其他亦相同 {AfxMessageBox("未找到匹配的子串"); } else { AfxMessageBox("匹配成功!"); }if(str.FindOneOf("AB") == -1) {//有A 或者 B 或者 AB都不會(huì)等于-1,這里要注意一下,區(qū)別在于這里AfxMessageBox("未找到匹配的子串"); } else {AfxMessageBox("匹配成功!"); }//我主要說一下他們的區(qū)別 //Find:完全匹配,只有完全匹配子串才ok; FindOneOf:非完全匹配,找到一個(gè)以上即可,找一個(gè)字符就相當(dāng)于完全匹配。3.11、MakeUpper、MakeLower、MakeReverse
void MakeUpper( ); //將小寫字母轉(zhuǎn)換為大寫字母 void MakeLower( ); //將大寫字母轉(zhuǎn)換為小寫字母 void MakeReverse( ); //顛倒字符串的順序CString str = _T("abCdEFG");//當(dāng)我們需要使用的字符串必須全部大寫的時(shí)候,我們用原字符串調(diào)用MakeUpper str.MakeUpper(); AfxMessageBox("轉(zhuǎn)換為大寫后:" + str); //此時(shí)彈窗輸出的就是 ABCDEFG//小寫亦同 str.MakeLower(); AfxMessageBox("轉(zhuǎn)換為小寫后:" + str); //此時(shí)彈窗的輸出: abcdefg//字符翻轉(zhuǎn),很多時(shí)候面試,就會(huì)讓我們翻轉(zhuǎn)數(shù)組或者字符串,感興趣可以去看下此函數(shù)的實(shí)現(xiàn),非常的精簡 str.MakeReverse(); AfxMessageBox("翻轉(zhuǎn)后:" + str); //output: gfedcba3.12、Replace
int Replace( TCHAR chOld, TCHAR chNew ); int Replace( LPCTSTR lpszOld, LPCTSTR lpszNew ); //用新的字符或者字符串替換老的字符或者字符串CString str = _T("0x11,0x12,0x13,0x14,0x15"); //倘若這是某服務(wù)器發(fā)送的莫一段程序中的內(nèi)存位置,現(xiàn)在我們要將逗號(hào)替換為換行符,換行顯示 std.Replace(',','\n'); //某系程序中解析是\r\n//輸出str AfxMessageBox(str); //顯示有換行輸出3.13、Delete、Insert、Remove
int Delete( int nIndex, int nCount = 1 ) //刪除字符,刪除從下標(biāo)nIndex開始的nCount個(gè)字符int Insert( int nIndex, TCHAR ch ) int Insert( int nIndex, LPCTSTR pstr ) //在下標(biāo)為nIndex的位置,插入字符或字符串。返回插入后對(duì)象的長度int Remove( TCHAR ch ); //移除對(duì)象內(nèi)的指定字符。返回移除的數(shù)目CString str = _T("123ABC789"); str.Delete(0,2); //3ABC789str.GetLength(); //7 str.Insert(0,"12"); str.GetLength(); //9str.Remove('8'); //如果字符串str中有多個(gè)8,那么,全部8都會(huì)被移除,然后返回移除后的GetLength()大小。在C++很多庫中或者同事封裝的類中會(huì)看見很多類似:
BOOL ChangeCharToVessel(char OldChar, char NewChar, size_t len = 5);這是C++中的新語法,函數(shù)重載,這里需要注意的是,如果你在形參中第二個(gè)參數(shù)中分配了默認(rèn)值,那么,第二參數(shù)后面不管有多少參數(shù),全部必須是有默認(rèn)值的,否則就報(bào)錯(cuò),C++分欄中我記得是有簡單說過一次函數(shù)重載,感興趣可以看看或者搜索一下,看看其他的都是OK的。
3.14、Format
格式化字符串forma("%d",12)意思是將一個(gè)整形的格式化的字符(我認(rèn)為是保持其形狀不變) 1).格式說明總是以%字符開始,以下是不同類型數(shù)據(jù)的格式方式%號(hào)后的說明: d輸出帶符號(hào)十進(jìn)制數(shù) o輸出無符號(hào)八進(jìn)制數(shù) x輸出無符號(hào)十六進(jìn)制數(shù) u輸出無符號(hào)數(shù) c輸出單個(gè)字符 s輸出一串字符 f輸出實(shí)數(shù)(6位小數(shù)) e以指數(shù)形式輸出實(shí)數(shù) g選用f與e格式中輸出寬度較小的格式,不輸出0 ld輸入輸出long型數(shù)據(jù) lf輸入輸出double型數(shù)據(jù) m數(shù)據(jù)輸出寬度為m .n輸出小數(shù)位數(shù)為n //示例: CString str; int len = 1024; str.Format(_T("%d"),len);AfxMessageBox("長度:" + str); //此方法跟C語言中的printf函數(shù)功能基本一樣,看大家怎么理解了3.15、GetBuffer、ReleaseBuffer
LPTSTR GetBuffer( int nMinBufLength ); //申請(qǐng)新的空間,并返回指針void ReleaseBuffer( int nNewLength = -1 ); //使用GetBuffer后,必須使用ReleaseBuffer以更新對(duì)象內(nèi)部數(shù)據(jù)CString csStr="abcde"; CString pStr=csStr.GetBuffer(10); strcpy(pStr,"12345"); csStr.ReleaseBuffer(); pStr=NULL; cout<<csStr //12345CString csStr="abc"; CString pStr=csStr.GetBuffer(10); strcpy(pStr,"12345"); cout<<csStr.GetLength(); //3(錯(cuò)誤的用法) csStr.ReleaseBuffer(); cout<<csStr.GetLength(); //5(正確) pStr=NULL;3.16、LoadString
CString::LoadStringBOOL LoadString( UINT nID );throw( CMemoryException );//返回值:如果加載資源成功則返回非零值;否則返回0。//參數(shù): nID 一個(gè)Windows字符串資源ID。 //說明: //此成員函數(shù)用來讀取一個(gè)由nID標(biāo)識(shí)的Windows字符串資源,并放入一個(gè)已有的CString對(duì)象中。//示例:下面的例子說明了如何使用CString::LoadString。 // CString::LoadString示例: #define IDS_FILENOTFOUND 1 CString s; if (! s.LoadString( IDS_FILENOTFOUND )) {AfxMessageBox("Error Loading String: IDS_FILENOTFOUND");... }04、常見類型轉(zhuǎn)換
平時(shí)我們?cè)贛FC編程的時(shí)候,會(huì)遇到很多類型的轉(zhuǎn)換、比如string 轉(zhuǎn) CString 等
注意和char 轉(zhuǎn)換時(shí),要把char定義成為const char,這樣是最安全的。
05、小結(jié)
關(guān)于MFC 中 CString 基礎(chǔ)類,單憑上面的這點(diǎn)東西肯定是無法以一概全的,但是我相信大家了解了上面的知識(shí)后,對(duì)于后面CString涉及的編程,想來會(huì)有自己的一點(diǎn)想法,這樣,假以時(shí)日,定能將這個(gè)基礎(chǔ)類拿捏得死死的。
上面有些方法我并沒有舉例或者說貼出代碼,其原因是,那些沒有貼出代碼的,我自己也沒有用過,不知道里面有哪些坑,如果我隨意貼出代碼,到時(shí)候出現(xiàn)了問題,可能會(huì)浪費(fèi)大家的時(shí)間,但是如果大家感興趣,可以一起討論一下關(guān)于CString 中遇到的問題。
版權(quán)說明:創(chuàng)作不易,僅此記錄自己學(xué)習(xí)的過程,轉(zhuǎn)載請(qǐng)注明出處,謝謝!
總結(jié)
以上是生活随笔為你收集整理的【MFC】MFC基础类——CString(使用心得)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: js解析lrc 实现lrc歌词同步滚动效
- 下一篇: Winamp栈溢出漏洞研究【转载】