要使用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_s
instead. 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》