[MFC] MFC basic class - CString (use experience)

01. Introduction to CString class

Preface: String operation is one of the most commonly used and basic operations in programming. As a VC programmer, whether you are a rookie or a master, you have used Cstring. And it seems that it is difficult to do without it in actual programming (although it is not a library in standard C++). Because the class provided in MFC is very convenient for us to operate strings, CString not only provides various rich operation functions and operator overloading, but also makes us use strings more intuitively as in basic; and it also provides dynamic memory Allocation allows us to reduce the hidden danger of how many string arrays are out of bounds. However, we also realized that CString is too error-prone during use, and some are unpredictable. So many experts came forward and suggested to abandon it.

Here, I personally think: CString is really perfectly encapsulated, and it has many advantages, such as "easy to use, powerful, dynamic memory allocation, it can save memory resources and high execution efficiency when copying a lot, and it is completely different from standard C Compatible, supports multi-byte and wide-byte at the same time, because it has an exception mechanism, it is safe and convenient to use.” In fact, the reason why it is easy to make mistakes during use is because we don’t know enough about it, especially its implementation mechanism. Because most of us don't like to go deep into the documentation about it at work, let alone it is in English.

CString is a very useful data type. They greatly simplify many operations in MFC, making MFC a lot more convenient when doing string operations. In any case, there are many special skills in using CString, especially for programmers coming from a pure C background, it is a bit difficult to learn. This article discusses these techniques.
  Using CString allows you to operate on strings more straightforwardly. This article is not a complete manual of CString, but it covers most of the common basic problems.

02. Common function table

It doesn't matter if you don't understand, I will describe it with examples below. If there is anything unclear, please comment in the comment area or chat with me privately. If you know it, I will try my best to explain it to you.

Function name describe Remark
CString CString class constructor slightly
GetLength Returns the number of characters in the CString object For multibyte characters, each 8-bit character is counted; that is, a leading byte and a trailing byte in a multibyte character are counted as two characters.
IsEmpty Tests whether a CString object contains no characters If it is empty, return 0; otherwise, return non-zero
Empty Forces the string to have 0 length Force empty string content
Geta returns the character at the given position Parameters should avoid negative numbers, otherwise unexpected results will appear
SET set the character at the given position Unexpected results when argument is negative or goes beyond end of object
Compare compares two strings case sensitive
CompareNoCase compares two strings not case sensitive
Collate compares two strings case sensitive, use locale specific information
CollateNoCase compares two strings Case-insensitive, use locale-specific information
Mid extract the middle part of the string For me, this function is mostly used for character matching and other functions
Right extract the right part of the string The Right function is generally used for CString segmentation or character segmentation in regular expressions
Left extract the left part of the string ditto
SpanIncluding extract substring containing only characters in set For me, the above three are enough
SpanExcluding Extract substrings containing only characters not in the set ditto, opposite meaning
Find find substring in parent string Parent string: Source string Substring: The searched string Substring must completely match the substring to be ok, otherwise return -1, if found, return the start subscript
ReverseFind Reverse lookup, same as above ditto
FindOneOf Find the first matching character from a set This is a non-exact match, stop searching when you find one (the example below explains slowly)
MakeUpper converts all characters in this string to uppercase Convert if there is one, do nothing if not, for foolproofing
MakeLower converts all characters in this string to lowercase ditto
MakeReverse As the name suggests, flips a string, i.e. a new string of characters from the end to the beginning If you are familiar with the data structure, you will know that this function is part of the reversal algorithm
Replace Replace indicated characters with other characters Secondary functions are high-frequency functions in string operations
Remove Remove indicator characters from string The return value is the number removed
Insert inserts a single character or substring at a given index in a string Returns the length of the inserted object
Delete remove one or more characters from a string Omit here
Format format string High Frequency Functions in High Frequency
FormatV Format a string as vsprintf I rarely use subfunctions
TrimLeft Trim leading whitespace characters from a string Leading space : refers to the space before the effective content of the variable or constant value
TrimRight Trim trailing whitespace characters from a string slightly
FormatMessage format message string MFC usually uses its own message box
GetBuffer Returns a pointer to the character in the CString Intermediate conversion function when converting CString to string
ReleaseBuffer Releases control of the buffer returned by GetBuffer slightly
LockBuffer Disable reference counting and protect strings in buffers basically useless
UnlockBuffer Enable reference counting, and release the string in the buffer ditto
LoadString Load an existing CString object from a Windows resource It is used to switch resources when multiple languages ​​are involved and language replacement is required

03. CString class member function example

3.1, CString (constructor)

Header file required for the CString class: #include <afx.h>, the following example is omitted, only the core code of the example is shown

//五种方法,以换行分割,请忽略变量名重名。
CString str;  //最简单的无参构造

CString str("ABCDE"); //带内容的构造
CString buf(str);  //类的拷贝构造
//buf输出:ABCDE

CString str("ABCDEFGH",3);
//str输出:ABC

CString str('a',5);
//str输出:aaaaa

wchar_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();  //6

str.Empty();  //强制清空内容

int len2 = str.GetLength(); //0

3.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);  //ABcD

3.7、Compare

int Compare( LPCTSTR lpsz ) const;
//区分大小写比较两个字符串,相等时返回0,大于时返回1,小于时返回-1

CString 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,小于时返回-1

CString 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: gfedcba

3.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);  //3ABC789

str.GetLength();  //7
str.Insert(0,"12");
str.GetLength();  //9

str.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                 //12345


CString 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::LoadString

BOOL 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,这样是最安全的。

// string 转 CString
CString str;
std::string strStr = "test";
str = strStr.c_str();


//CString 转 string
std::string buf;
CString str = _T("test");
buf = str.GetBuffer(str.GetLength());

//string 转 char*
const char* p = NULL;
std::string buf = "aaaaa";
p = buf.c_str();

//char* 转 string
const char* p = "ttttt";
std::string buf(p);

//CString 转 char*
CString str(_T("aaa"));
const char* buf = NULL;
strcpy(buf ,str,sizeof(buf ));

//char* 转 CString
CString str;
const char* buf = "test is ok";
str.Format(_T("%s"),buf);



//
// CStringA转CStringW
//
CStringW CStrA2CStrW(const CStringA &cstrSrcA)
{
    
    
    int len = MultiByteToWideChar(CP_ACP, 0, LPCSTR(cstrSrcA), -1, NULL, 0);
    wchar_t *wstr = new wchar_t[len];
    memset(wstr, 0, len*sizeof(wchar_t));
    MultiByteToWideChar(CP_ACP, 0, LPCSTR(cstrSrcA), -1, wstr, len);
    CStringW cstrDestW = wstr;
    delete[] wstr;
 
    return cstrDestW;
}


//
// CStringW转CStringA
//
CStringA CStrW2CStrA(const CStringW &cstrSrcW)
{
    
    
    int len = WideCharToMultiByte(CP_ACP, 0, LPCWSTR(cstrSrcW), -1, NULL, 0, NULL, NULL);
    char *str = new char[len];
    memset(str, 0, len);
    WideCharToMultiByte(CP_ACP, 0, LPCWSTR(cstrSrcW), -1, str, len, NULL, NULL);
    CStringA cstrDestA = str;
    delete[] str;
 
    return cstrDestA;
}

05、小结

关于MFC 中 CString 基础类,单凭上面的这点东西肯定是无法以一概全的,但是我相信大家了解了上面的知识后,对于后面CString涉及的编程,想来会有自己的一点想法,这样,假以时日,定能将这个基础类拿捏得死死的。

上面有些方法我并没有举例或者说贴出代码,其原因是,那些没有贴出代码的,我自己也没有用过,不知道里面有哪些坑,如果我随意贴出代码,到时候出现了问题,可能会浪费大家的时间,但是如果大家感兴趣,可以一起讨论一下关于CString 中遇到的问题。

版权说明:创作不易,仅此记录自己学习的过程,转载请注明出处,谢谢!

Guess you like

Origin blog.csdn.net/m0_43458204/article/details/119026654
Recommended