最近学了两天MFC
,发现还比较有意思,准备过一段时间买一本《深入浅出MFC》,去好好学一下图形界面的框架以及其内部对系统调用的使用。
在使用MFC
的时候,虽然界面和其表面逻辑框架都是使用MFC的,但其实大部分的内部逻辑我还是使用C++
原生库去写的,比如今天花了两个小时写了两个MFC
小程序——输入型多项式计算器(中缀转后缀,支持加减乘除括号的混合运算)、一个简单的汉英词典软件(解决一下自己平常打代码的时候的命名问题),其内部逻辑都是用C++
内部自带的库(STL
等)和命名空间std去实现的。
由于上面的两个小Demo都用到了比较多的字符串处理,而内部逻辑使用的是std::string
,而在MFC
这边,我取得的Edit_Control
中的数据是CString
类型的,所以就要经过一些简单的转换。
所以,下面对CString
和C++自带字符串类型(std::string
)之间,进行转换的方法做一个小总结吧。
经过这几天的搜索学习,我发现网上介绍CString
的东西特别少,所以我先介绍一下CString
CString
CStringT
,实际上它是一个操作可变长度字符串的模板类。CStringT
模板类有三个实例:CString、CStringA
和CStringW
,它们分别提供对TCHAR
、char
和wchar_t
字符类型的字符串的操作。char
类型定义的是Ansi
字符,wchar_t
类型定义的是Unicode
字符,而TCHAR
取决于MFC工程的属性对话框中的Configuration Properties->General->Character Set
属性,如果此属性为Use Multi-Byte Character Set
,则TCHAR
类型定义的是Ansi
字符,而如果为Use Unicode Character Set
,则TCHAR
类型定义的是Unicode
字符。
几个常用函数:
CString& MakeLower();
将字符串中的所有大写字符转换为小写字符。
CString& MakeUpper();
将字符串中的所有小写字符转换为大写字符。
CString& MakeReverse();
将字符串中所有字符的顺序颠倒。
CString对象的连接
多个CString
对象的连接可以通过重载运算符+、+=
实现。例如:
CString str(_T("google")); // str内容为"google"
str = _T("www.") + str + _T("."); // str为"www.google."
str += _T("com"); // str为"www.google.com"
CString对象字符串的提取操作
CString Left(int nCount) const;
提取该字符串左边nCount
个字符的子字符串,并返回一个包含这个子字符串的拷贝的CString
对象。
CString Right(int nCount) const;
提取该字符串右边nCount
个字符的子字符串,并返回一个包含这个子字符串的拷贝的CString
对象。
CString Mid(int iFirst,int nCount) const;
提取该字符串中以索引iFirst
位置开始的nCount
个字符组成的子字符串,并返回一个包含这个子字符串的拷贝的CString
对象。
CString Mid(int iFirst) const;
提取该字符串中以索引iFirst
位置开始直至字符串结尾的子字符串,并返回一个包含这个子字符串的拷贝的CString
对象。
如下:
CString str1 = _T("google");
CString str2 = str1.Left(3); // str2为"goo"
str2 = str1.Right(2); // str2为"le"
str2 = str1.Mid(1,3); // str2为"oog"
str2 = str1.Mid(5); // str2为"le"
CString类的格式化字符串方法
使用CString
类的Format
成员函数可以将int、short、long、float、double
等数据类型格式化为字符串对象。
void __cdecl Format(PCXSTR pszFormat,[, argument]...);
参数pszFormat
为格式控制字符串;参数argument
可选,为要格式化的数据,一般每个argument
在pszFormat
中都有对应的表示其类型的子字符串,int
型的argument
对应的应该是"%d"
,float
型的应对应"%f"
,等等。
例如:
CString str;
int a = 1;
float b = 2.3f;
str.Format(_T("a=%d,b=%f"), a, b); // str为"a=1,b=2.300000"
CString
和std::string
的相互转换
CString
-> string
这里我使用了一下网上查到的方法,发现并不能用,其实想一想也对,string
内置存储的是一个字节长的char
类型字符,而CString
存储的是两字节长的wchar_t
类型。不能相互转换也比较正常,虽然可以直接强行转换。但也太过于粗暴了。
但是有一点我觉得比较奇怪,因为在我印象中string
虽然内部是char
类型的元素,但是在初始化的时候,会自动将那个汉字元素扩充成两个字符位置进行存储。
比如如下代码:
int main()
{
string str = "hi,你好";
return 0;
}
调用调试,我们可以很容易的发现string
内部的存储形式为如下方式:
可以发现,string
内部还是使用的char
类型进行汉字的存储,不过却是使用的两个char来存储。
不过如果我们如果单独用wchar_t
字符串对string
进行初始化,就会出错。
所以我们在使用CString
对string
挨个元素进行初始化的时候,发现string
内部的元素却是使用的一个char
进行存储wchar_t
,这就导致了无法用CString
对string
进行初始化的问题。
这样的字符转码真的导致了很大的问题,而且不好解决。解决方式有以下几种:
- 我们可以使用
wstring
来进行字符串的存储和输出,然后用一对一的下标赋值的方式进行解决 - 也可以直接用vs2015左右版本支持的方式
CT2A
(之前版本的也应该有相应的转换宏定义,不过是不是这个就不一定了,可以去查一下官方手册):
string c_str("你好");
string str = CT2A(mfc_str);
- 用
GetBuffer(0)
然后加一点转换,记得ReleaseBuffer()
CString mfc_str("Nihao1");
string str(CT2CA(mfc_str.GetBuffer(0)));
还是自己学的不好啊,看来这些基础还要再次重温一下。
string
->CString
相对于上面的转换,下面的转换就很简单了,直接用如下代码就OK:
string p("你好");
CString Cstr(p.c_str());
真的是…..很奇特。
就这样吧,等有空了再仔细看看字符的不同编码方式之间的转换吧。