C风格字符串
C风格字符串不是一种类型,而是为了表达和使用字符串而形成的一种约定俗成的写法。C风格字符串存放在字符数组中并以空字符(
\0
)结束,一般利用指针来操作字符串。
C语言标准库提供了可用于操作C风格字符串的一些函数,定义在cstring头文件中。
C风格字符串的函数 | |
---|---|
size_t strlen(const char *p) | 返回p的长度,空字符不计算在内。 |
int strcmp(const char *p1, const char *p2) | 比较p1和p2的相等性,如果p1 == p2, 返回0;如果p1 > p2,返回一个正值;如果p1 < p2,返回一个负值。 |
char *strcat(char *p1, const char *p2) | p2附加到p1之后,返回p1。 |
char* strcpy(char *p1, const char *p2) | p2拷贝给p1,返回p1. |
// 以下操作将引发错误
char ca[] = {'C', '+', '+'};
// 严重错误,strlen函数将有可能沿着ca在内存中的位置不断向前寻找知道遇到空字符
cout << strlen(ca) << endl;
采用比较运算符(<、>)比较两个C风格字符串,实际上比较的是指向数组首元素的指针而非字符串本身,进行比较的两个指针应该指向同一对象,否则得到的将是为定义的结果:
const char ca1[] = "A string example";
const char ca2[] = "A different string";
if (ca1 < ca2) { // 为定义的:试图比较两无关的地址
//..
}
// 比较两个字符串本身
if (strcmp(ca1, ca2) < 0) {
// ...
}
附加及拷贝字符串操作,必须提供一个用于存放结果字符串的数组,且该数组必须足够大一边容纳下结果字符串(包括空字符)
// 以下代码极易导致严重漏洞,因为largeStr所需的空间不容易被估计
strcpy(largeStr, ca1);
strcat(largeStr, " ");
strcat(largeStr, ca2);
一般来说,不建议使用C风格字符串,后面的笔记会介绍更安全高效的标准库类型string。
练习:编写一段程序,定义两个字符数组并用字符串字面值初始化它们;接着再定义一个字符数组存放前两个数组连接后的结果。使用strcpy和strcat把前两个数组的内容拷贝到第三个数组中。
// cpycat.cc
#include <iostream>
#include <cstring>
int main() {
char ca1[] = "Hello,";
char ca2[] = "World!";
char ca3[16];
strcpy(ca3, ca1);
strcat(ca3, ca2);
std::cout << ca3 << std::endl;
return 0;
}
$ ./cpycat.out
Hello,World!