char string 区别
由于在C++项目中,经常遇到处理字符方面的问题,故借此机会整理一下,让自己对于char , string 等有进一步的了解。
- 基本概念
由单引号括起来的一个字符成为char型字面值。双引号括起来的零个或多个字符则构成字符串型字面值。
'a' // 字符字面值 "Hello World!"//字符串字面值
字符串字面值得类型=>由常量字符构成的数组,并在结尾处添加一个空字符('\0');因此字符串字面值的实际长度比它的内容多1。
'A'//单独的字符A
"A"//包含两个字符,一个字母A,一个空字符。
- C标准库String函数
strlen(p) | 返回p的长度,空字符不计算在内,传入此类函数的指针必须纸箱以空字符作为结束的数组。 |
strcmp(p1,p2) |
比较p1和p2的相等性。如果p1 == p2,返回0;如果p1>p2,返回一个正值;如果p1<p2,返回一个负值。 传入此类函数的指针必须纸箱以空字符作为结束的数组。 |
strcat(p1,p2) | 将p2附加到p1之后,返回p1;传入此类函数的指针必须纸箱以空字符作为结束的数组。 |
strcpy(p1,p2) | 将p2拷贝给p1,返回p1;传入此类函数的指针必须纸箱以空字符作为结束的数组。 |
char ca [] = {'C', '+', '+'}; //不以空字符结束 cout << strlen(ca)<<endl; //错误,ca没有以空字符结束
当使用数组的时候,其实真正用的是指向数组首元素的指针。
混用string对象和C风格字符串
- 允许使用以空字符结束的字符数组来初始化string对象或为string对象赋值;
- 在string对象的加法运算中允许使用以空字符结束的字符数组作为其中一个运算对象(不能两个运算对象都是);在string对象的复合赋值运算中允许使用以空字符结束的字符数组作为右侧的运算对象。
上述返过来就不行,如下:
不能用string对象直接初始化指向字符的指针。为此,string提供了c_str的成员函数,来实现此效果。
string s("Hello World"); //可以,s内容是 Hello World char * str = s; //错误 const char *str = s.c_str(); //正确 ,注意是 const char *
c_str函数返回结果是一个指针,指向一个以空字符结束的字符数组,而这个数组所存的数据恰好与那个string对象的一样。结果指针的类型是const char *,从而确保我们不会改变字符数组的内容。
注意:c_str()返回的数组无法保证一直有效,如果后续的操作改变了s的值,就可能让之前返回的数组失效。
如果执行完c_str()函数后程序想一直都能使用其返回的数组,最好将该数组重新拷贝一份。
- 标准库类型 String
标准库string表示可变长的字符序列,首先要包含string头文件,且string定义在命名空间std中。
string s1 ;//默认初始化,s1是一个空串 string s2(s1); // s2 是 s1 的副本 string s2 = s1; // 等价于s2(s1),s2 是s1的副本 string s3("value") ;//s3是字面值value的副本,不过没有后面的那个空字符 string s3 = "value";//等价于s3("value"),s3 是字面值"value"的副本。 string s4(n,'c'); // 把s4初始化为由连续n个字符c组成的串。
有关标准类型String对象上的操作有s.size() s.empty() s1+s2 s1 = s2 s[n] s1==s2 < <= > >= !=
- 数组方面
字符数组的特殊性:它有一种额外的初始化形式,可以用字符串字面值对此类数组初始化。
char a1[] = {'C', '+', '+'};//列表初始化,没有空字符 char a2[] = {'C', '+', '+','\0'}; // 列表初始化,含有显式的空字符 char a3[] = "C++" ;//会自动添加表示字符串结束的空字符 const char a4[6] = "Daniel"; //错误,没有空间可存放空字符
string 类型数组:
string a4[3] = {"hi","bye"};//等价于a4[] = {"hi","bye",""};
在C语言中,可以使用以下方式:
char *str ="hello world"; //但是这种方式在IOS C++11 运行下不行。
C语言有两种表示字符串的方法,一种是字符数组,另一种是字符串常量,它们在内存中的存储位置不同,使得字符数组可以读取和修改,而字符串常量只能读取不能修改。
#include <stdio.h> int main(){ char *str = "Hello World!"; str = "I love C!"; //正确 str[3] = 'P'; //错误 return 0; }
在编程过程中如果只涉及到对字符串的读取,那么字符数组和字符串常量都能够满足要求;如果有写入(修改)操作,那么只能使用字符数组,不能使用字符串常量。
这两种方式(字符数组和字符串指针)它们最根本的区别是在内存中的存储区域不一样,字符数组存储在全局数据区或栈区,第二种形式的字符串存储在常量区。全局数据区和栈区的字符串(也包括其他数据)有读取和写入的权限,而常量区的字符串(也包括其他数据)只有读取权限,没有写入权限。
还有一点需要注意,就是当用到sizeof时:
char *str1 = "hello wrold"; char str2[] = "hello world"; cout<<sizeof(str1); //8 机子是64位 cout << sizeof(str2); //12
推荐阅读