再谈字符串操作

来源:互联网 发布:openwrt 网络重启命令 编辑:程序博客网 时间:2024/05/22 17:36

C/C++编程中,操作字符串是很常用的编程技术。之前转载过一篇《CStringintstringchar*之间的转换》的文章。其中的CStringstringchar*都是为了表示字符串的类型,而int是数字的整型类型,那么字符串和数字之间为什么要转换呢?

 最近又翻看了一遍《C++ Primer Plus 6》,里面多次提到数字和字符串的转换是cout的实现基础,我们知道cout只能将字符串打印到屏幕上,因此在打印之前,必须将整数形式的数字转换为字符串形式。如-2.34,需要将5个字符(-2.34)而不是这个值得64位内部浮点表示发送到屏幕上,因此ostream类最重要的任务之一是将数值类型(intfloat)转换为以文本形式表示的字符流。

 这篇我们先再重点复习一下“字符串”的概念。

字符串:存储在内存的连续字节中的一系列字符C++处理字符串的方式有两种。第一种来自C语言,常被称为“C-风格字符串”;另一种基于string类库。而上文提到的CString则特指在Windows操作系统上进行MFC程序开发时使用的一种类型。

 这里简单说明一下C-风格字符串”:它来自C语言,C-风格字符串具有一种特殊的性质,以空字符结尾,空字符被写作\0,其ASCII码为0,用来标记字符串的结尾。比如下面两个声明:

char dog[7 ] = {‘b’, ‘e’, ‘a’, ‘u’, ‘x’, ‘’, ‘I’};char cat[7] = {‘f’, ’a’, ‘b’, ‘c’, ‘g’ , ‘e’, ‘\0’};

dog只是字符数组,cat才字符串。

 一般我们使用下面的形式来初始化字符数组:

const int Size = 15;char name[Size] = “C++owboy”;

这里“C++owboy”叫字符串常量(字符串字面值):用双引号括起来的一些字符。它隐式地包括结尾的空字符。

 c++新增string类之前,程序员也需要完成诸如给字符串赋值等工作。对于C-风格字符串,程序员使用C语言库中的函数来完成这些任务。例如,可以使用函数strcpy()将字符串复制到字符数组中,使用函数strcat()将字符串附加到字符数组末尾。

 

了解完上面这些概念,我们就可以理解并掌握各种字符串类型之间的转换了。首先char*和字符串数据可以认为是等同的,转换关系如下:

char temp[80] = "hello world";int len = strlen(temp);    //计算字符串长度  char *pn = new char[len + 1];    //分配存储空间  strcpy_s(pn, len + 1, temp); //将s中字符串复制到str,最后一个空间为'\0'结束符  cout << pn << endl;delete[] pn;

C++ Primer 6 plusP270中提到string类定义了一种char*string的转换功能。这样char*string的转换就很简单了:

char *p = “hello”;

string str(p);

或者先声明再赋值:

string str;str = p;

string的函数c_str(函数声明const char *c_str();)返回当前字符串的首字符地址。因此stringchar*的转换:

注意:一定要使用strcpy()函数 等来操作方法c_str()返回的指针

比如:最好不要这样:

char* c;string s="1234";c = s.c_str();

//c最后指向的内容是垃圾,因为s对象被析构,其内容被处理(纠正:s对象的析构是在对指针c完成赋值操作之后进行的,故此处并没有错误)

应该这样用:

char c[20];string s="1234";strcpy(c,s.c_str());

这样才不会出错,c_str()返回的是一个临时指针,不能对其进行操作。

 

char*CString的转换与char*string的转换一样。而CStringchar*的转换需要区分是基于Use Multi-Byte Charecter Set还是Use Unicode Charecter Set。

Use Multi-Byte Charecter Set下:

CString str1 ="123";  char *t1 =str1.GetBuffer(str1.GetLength());  str1.ReleaseBuffer();  

多字节下CStingint的转换:

CString str1 ="123";  int i =atoi(str1);  

Use Unicode Charecter Set下:

CString str1 =_T("123");  int len =WideCharToMultiByte(CP_ACP,0,str1,-1,NULL,0,NULL,NULL);  char *ptxtTemp =new char[len +1];  WideCharToMultiByte(CP_ACP,0,str1,-1,ptxtTemp,len,NULL,NULL );    //...  delete[] ptxtTemp;  

UnicodeCStingint的转换:

CString str2 =_T("100");  int i;  swscanf(str2,_T("%d"),&i);  

 

多字节下CStringstring的转换有下面两个办法:

CString str("hello world");string s1 = str.GetBuffer(0);string s11 = LPCSTR(str);

stringCString的转换如下:

string str = "hello world";CString s1,s2;s1.Format( "%s", str.c_str() );s2.Format( "%s", str.data() );


stringint之间的相互转换:

1)采用标准库中atoi函数。

string s = "12";int a = atoi(s.c_str());
对于其他类型也都有相应的标准库函数,比如浮点型atof(),longatol()等等。

2)采用sstream头文件中定义的字符串流对象来实现转换。

istringstream is("12"); //构造输入字符串流,流的内容初始化为“12”的字符串int i;is >> i; //从is流中读入一个int整数存入i中

3)采用标准库中的to_string或sprintf_s函数。

int i = 12;cout << std::to_string(i) << endl;
不需要包含任何头文件,应该是在utility中,但无需包含,直接使用,还定义任何其他内置类型转为string的重载函数,很方便。

 

int i = 123;char buf[30] = {};sprintf_s(buf, “%d”, i);

4)采用sstream中定义的字符串流对象来实现。

ostringstream os; //构造一个输出字符串流,流内容为空int i = 12;os << i; //向输出字符串流中输出int整数i的内容cout << os.str() << endl; //利用字符串流的str函数获取流中的内容

字符串流对象的str函数对于istringstreamostringstream都适用,都可以获取流中的内容。