要使用string类,必须在程序中包含头文件string。string类位于名称空间std中
1 | string name1 = "hello"; |
这里有两个注意点
- 字符串可以通过
==比较,且name1 == name3 - 字符串可以通过
char[]表示,且相等 - 字符数组后面有一个
‘\0’
C++11也允许将列表初始化用于C-风格字符串和string对象:
1 | char charr1[20]; |
输出结果
1 | Enter a kind of feline: hello |
所以
- 可以使用C-风格字符串来初始化string对象。
- 可以使用cin来将键盘输入存储到string对象中。
- 可以使用cout来显示string对象。
- 可以使用数组表示法来访问存储在string对象中的字符。
对于一个数组,返回这个数组占的总空间,所以 sizeof(name2) 取的额是字符串name2占的总空间
头文件cstring(以前为string.h)提供了字符串操作函数
1 | char *strcpy(char *__dst, const char *__src); //copy __src to __dst |
接着看看实际操作
1 | string str1 = "hello"; |
运行结果
1 | hello hello |
可以得出几点:
strcpy是复制,不会影响原来的字符串string类可以直接使用 = 复制,并且也不会影响原来的string转换为const char *,因为const char *是一个指向字符常量的指针,类型不匹配- 使用
strcpy注意目标空间大于等于源目标,否则导致目标缓冲区异常,导致崩溃或未知错误
计算字符长度也是不一样的
1 | char name1[6] = "world"; |
输出结果
1 | 5 5 5 |
1 | char name[20]; |
运行结果
1 | hello world #输入 |
getline()是 C++ 标准库中的一个自由函数(不是成员函数),用于从标准输入流cin中读取一行文本,并将其存储到std::string对象str中cin.getline()是istream类的成员函数,用于从标准输入流cin中读取一行文本,并将其存储到字符数组name中
C++11 新增了原始字符串,字符表示的就是自己
1 | cout << R"(Jim "King" Tutt users "\n" instead of endl.)" << '\n'; |
输入结果
1 | Jim "King" Tutt users "\n" instead of endl. |
原始字符串将 (和)用作定界符,并使用前缀 R 来标识原始字符串
也可以使用 R"+*( 表示原始字符串的开头的时候,必须使用 )+*" 标识原始字符串的结尾
最后看一波 strcpy 的源码实现
1 | char* strcpy(char* dest, const char* src) { |
src为指针常量不会被修改- 定义一个指针
tmp并将其指向目标字符串dest的起始地址。这样在复制结束后,可以通过tmp指针找到复制后的目标字符串的起始地址,并返回该指针
实际的使用中会发现 strcpy 几乎不是用,原因是 strcpy当一直遍历到 src 结束才会停止写入 dest,当 src 长度大于 dest 的时候,会导致溢出
就提到了另外函数 strncpy
1 | char *strncpy(char *dest, const char *src, size_t count) |
这里有几个关键的问题
-
*temp != 0进行判断是否结束,不是\0吗?'0'代表ASCII值为48的数字零字符,而'\0'代表空字符(null terminator),其ASCII值为0 -
如果
src_len >= count会怎样?src的全部内容都回被copy 到dest中,但是dest末尾并不是\0 -
如果
src_len < count,tmp++直到count == 0,也就是说超过count的部分不变1
2
3
4char arr[6] = "world";
char dest[12] = "hello world";
strncpy(dest, arr, 8);
cout << dest << endl;输出结果
world, 是因为将'\0'也复制进去了,那是不是当超过src_len < count就可以结束了
在使用 strncpy 又会有一个新的提示
This function or variable may be unsafe. Consider using
strncpy_sinstead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details
下面是 strcpy_s 的实现
1 | _FUNC_PROLOGUE |
也就是 strcpy_s 除了字符校验还解决了当 dest_len < cout 时候的溢出
参考链接
- 《C++ Primer Plus》