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