字符串之间转换:
CString 头文件#include <afx.h>
string 头文件#include <string.h>
◆CString 转char *
①CString cstr;
char *p = (LPSTR)(LPCTSTR)cstr;
②CString strtest;
char * charpoint;
charpoint=”give string a value”;
strtest=charpoint;
③CString转换 char[100]
char a[100];
CString str(”aaaaaa”);
strncpy(a,(LPCTSTR)str,sizeof(a));
◆char 转 CString
CString.format(”%s”, char*);
◆string 转 CString
CString.format(”%s”, string.c_str());
用c_str()确实比data()要好.
◆CString 转 string
string s(CString.GetBuffer());
GetBuffer()后一定要ReleaseBuffer(),否则就没有释放缓冲区所占的空间.
◆char 转 string
string s(char *);
只能初始化,在不是初始化的地方最好还是用assign().
◆string 转 char *
char *p = string.c_str();
字符串和数字之间的转换
◆CString互转int
将字符转换为整数,可以使用atoi、_atoi64或atol。
◆int转换为CString
可以使用CString的Format函数。如
CString s;
int i = 64;
s.Format(”%d”, i)
Format函数的功能很强,值得研究一下。
◆ Int和char*或std::string之间的转换
① C数据转换函数族
C数据转换函数族即包括itoa、atoi等数据类型转换函数在内的一大批C函数,在C语言时代曾经被大量使用。源代码如下:
int i = 10;
char szBuf[10] = "";
itoa(i, szBuf, 10);
cout<<"itoa: szBuf = "<<szBuf<<endl;
i = 0;
i = atoi(szBuf);
cout<<"atoi: i = "<<i<<endl;
使用还是比较简单的。一个最大的问题是:没有进行char*的越界检查,可能会造成数组溢出。
②snprintf/sscanf
sprintf是用来格式化字符串的一个C函数,sscanf则是从字符串中读取值的一个C函数。由于Herb Sutter(Exceptional C++系列著作的作者)教导我们“永远也不要使用sprintf”,所以这里我们只使用snprintf。由于snprintf进入C标准较晚,所以在你的编译器中也许只能使用非标准的_snprintf(例如我的VC6平台)。源代码如下:
int i = 20;
char szBuf[10] = "";
memset(szBuf, 0, sizeof(szBuf));
_snprintf(szBuf, sizeof(szBuf), "%d", i);
cout<<"_snprintf: szBuf = "<<szBuf<<endl;
i = 0;
sscanf(szBuf,"%d",&i);
cout<<"sscanf: i = "<<i<<endl;
使用很简单,而且,似乎没有什么内存泄露或者数组越界。
③ std::stringstream
对流很熟悉的人可能会更快适应std::stringstream的解决方案:
#include <sstream>
using namespace std;
int i = 30;
string strRel;
ostringstream oss;
oss<<i;
strRel = oss.str();
cout<<"ostringstream: strRel = "<<strRel<<endl;
i = 0;
istringstream iss(strRel);
iss>>i;
cout<<"istringstream: i = "<<i<<endl;
使用较为复杂,而且,还使用了两个临时变量oss和iss,这必然带来性能上的开销。
◆double和char*或std::string之间的转换
①C数据转换函数族
当开始进行double和char*之间的转换时,C数据转换函数的缺点暴露无疑。先看源代码:
double d = 3.1415926;
char szBuf[18] = "";
_gcvt(d, 9, szBuf);
cout<<"_gcvt: szBuf = "<<szBuf<<endl;
d = 0;
char* stopstring;
d = strtod(szBuf, &stopstring);
cout<<"strtod: d = "<<d<<endl;
首先转换函数的名字就让人大吃一惊,与itoa对应的不是我们想象的dtoa,而是_gcvt,而与atoi对应的是strtod。其次它们的参数很奇怪,没有msdn是不可能明白的。其次,数组越界依然存在。至此我想我们可以抛弃这组函数了。当然,更加无奈的理由在后面。
snprintf/sscanf
snprintf/sscanf表现不错,源代码如下:
double d = 3.1415926;
char szBuf[18] = "";
memset(szBuf, 0, sizeof(szBuf));
_snprintf(szBuf, sizeof(szBuf), "%f", d);
cout<<"sprintf: szBuf = "<<szBuf<<endl;
sscanf(szBuf, "%f", &d);
cout<<"sscanf: d = "<<d<<endl;
很好,很强大!
std::stringstream
std::stringstream的代码似乎没有任何改动,除了一个int类型改成了double类型:
double d = 9.1415926;
string strRel;
ostringstream oss;
oss<<d;
strRel = oss.str();
cout<<"ostringstream: strRel = "<<strRel<<endl;
d = 0;
istringstream iss(strRel);
iss>>d;
cout<<"istringstream: d = "<<d<<endl;
◆复杂的转换
考虑一个经典的场景,从一个int,一个double和一个string中读出值,然后拼凑为一个输出的字符串。最后,从这个字符串中再将这几个值读出来。
C数据转换函数族
直接看代码:
int iAge = 25;
float fPayment = 3.25;
string strName ="Wang";
char szBuf[100] = "";
char szTemp[100];
strcpy(szBuf,"Age= ");
itoa(iAge, szTemp, 10);
strcat(szBuf, szTemp);
strcat(szBuf," ,Payment= ");
_gcvt(fPayment, 4, szTemp);
strcat(szBuf,szTemp);
strcat(szBuf," ,Name= ");
strcat(szBuf, strName.c_str());
cout<<"szBuf = "<<szBuf<<endl;
以上代码的表现真是惨不忍睹,费了几鼻子的劲好歹是转为目标字符串了。转换回来的代码也没有写。也许有,不过那个复杂程度,我看还是算了。而且,strcpy、strcat和几个转换函数都是危险的API,不检查越界的。
snprintf/sscanf
主要看看sscanf的表现:
int iAge = 25;
float fPayment = 3.25;
string strName ="Wang";
char szBuf[100] = "";
memset(szBuf, 0, sizeof(szBuf));
_snprintf(szBuf, sizeof(szBuf), "Age = %d, Payment = %f, Name = %s",iAge,fPayment,strName.c_str());
cout<<"sprintf: szBuf = "<<szBuf<<endl;
iAge = 0;
fPayment = 0.0;
memset(szTemp, 0, sizeof(szTemp));
sscanf(szBuf,"Age = %d, Payment = %f, Name = %s",&iAge,&fPayment,&szTemp);
strName = szTemp;
cout<<"sscanf: Age = "<<iAge<<",Payment="<<fPayment<<",name="<<strName<<endl;
snprintf表现还是一如既往的强大。sscanf的表现简直就是perfect,但是要注意,sscanf的样式字符串一定要和snprintf中的样式字符串一模一样,否则其后果是不可预计的。例如,我稍微改动了几个字符,最后的strname就读取错误了。
std::stringstream
std::stringstream的代码很长很长:
int iAge = 25;
float fPayment = 3.25;
string strName ="Wang";
string strRel;
ostringstream oss;
oss<<"Age = "<<iAge<<", Payment = "<<fPayment<<", Name = "<<strName;
strRel = oss.str();
cout<<"ostringstream: strRel = "<<strRel<<endl;
iAge = 0;
fPayment = 0.0;
strName = "";
istringstream iss(strRel);
string strTemp;
iss>>strTemp>>strTemp>>iAge>>strTemp>>strTemp>>strTemp>>fPayment
>>strTemp>>strTemp>>strTemp>>strName;
cout<<"istringstream: Age = "<<iAge<<",Payment="<<fPayment<<",name="<<strName<<endl;
ostringstream的表现还是不错的,比snprintf毫不逊色,甚至更好一点,因为它不用记样式符。但是看到istringstream的这几行代码,估计大部分人要吐血了:
string strTemp;
iss>>strTemp>>strTemp>>iAge>>strTemp>>strTemp>>strTemp>>fPayment
>>strTemp>>strTemp>>strTemp>>strName;
为什么中间有那么多strTemp?因为每当istringstream每当遇到由一个空格或者非数字字符包围的字符串时就必须输入到一个string中,因此例如“,”或者“=”都必须占用一个string来输入。总之,当字符串很复杂时,很麻烦。