C++处理字符串有两种方式:
C风格字符串
String类
一、C风格
首先,什么是字符串?字符串是存储在内存连续字节中的一系列字符。这就意味着可以将字符串存储在字符数组中。C风格的字符串具有一项特殊性质,即以空字符’\0’结尾。很多字符串处理函数都以空字符为依据来结束操作。
a[10] = {'w','o','n','e','\0'};
b[] = "wone"; //'\0'被隐藏起来了,但依然存在。
//tip:指针与字符串
char *c = "aabbcc"; //这种方式有可能发生通过指针c去修改“aabbcc”这个处于常量区的字符串,最终引发未知错误。
const char *c = "aabbcc"; //因此最好使用这种方式,避免了通过c去修改字符串中的内容。
上面的代码展示了两种初始化字符数组的方式,其中第二种方式是用字符串常量对字符数组进行初始化,不要将b也误认为字符串常量(const char *),b仍然可以对其中的元素进行修改。
tips
sizeof(a) = 10; //siezeof求的是整个a数组的内存大小
strlen(a) = 4; //strlen求的是除空字符外的字符数
一个有意思的缺陷:
//代码示例
char name[20];
char address[20];
cin>>name;
cin>>address;
cout<<"Name:"<<name<<" Address:"<<address<<endl;
//执行
输入: will smith
此时用户还没有输入地址,程序已经将结果输出:
Name:will Address:smith
cin在读取键盘输入时,cin会认为空格符就是当前输入的结束,因此将空格之前的will获取到。随后当需要输入地址时,由于smith还在缓存中,便将其当作地址的输入获取到。
为了避免该缺陷,我们可以使用面向行的输入,它以回车作为字符串结束标志,两个函数:cin.get()以及cin.getline();
二、String
需要包含头文件< string >
string str1;
string str2 = "wone";
String较之字符数组的不同:
1.String对象能够自动调整自己的大小,不用担心内存是否足够,与使用数组相比,这更安全。
2.字符数组不能直接赋值给另一个字符数组(当然,这是数组的通性),而string对象可以直接赋值给另一个string。字符数组要完成这种操作都是使用C库函数进行,如strcpy();
3.因为重载了运算符,String对象可以直接使用+、+=来进行拼接以及附加。
4.STL的一种,支持迭代器。
字符串遍历
char* :
int main() {
char* str = "Hello";
while (*str != '\0') {
std::cout << *str << " ";
str++;
}
return 0;
}
//注意这种方式结束后,str指针就不再指向字符串首字符地址了,
//以后也无法通过str来对字符串进行正确操作。
//可以参考下面char[]遍历的方式,用另外一个指针来进行遍历。
char [] :
int main() {
char arr[] = "Hello";
// planA
char* ptr = arr;
while (*ptr != '\0') {
printf("%c ", *ptr);
ptr++;
}
// planB
for (int i = 0; arr[i] != '\0'; i++) {
std::cout << arr[i] << " ";
}
return 0;
}
string :
int main() {
std::string str = "Hello";
// planA:
for (size_t i = 0; i < str.length(); i++) {
std::cout << str[i] << " ";
}
// planB:
for (std::string::iterator it = str.begin(); it != str.end(); ++it) {
std::cout << *it << " ";
}
// planC
for (char c : str) {
std::cout << c << " ";
}
return 0;
}