专栏网址:https://blog.csdn.net/zhujushu/category_13112687.html
0.概述
C 风格字符串是以 '\0'结尾的字符数组,表示字符串的结束。
<cstring> 库继承自 C 语言,是 C++ 标准库的一部分,用于操作 C 风格字符。
C 风格字符串与 C++ 字符串对象 (std::string) 不同,因为它们是低级的,并且依赖于原始内存操作。
<cstring> 库提供了各种用于操作 C 风格字符串的函数,例如复制、连接、比较和搜索。这些函数将 C 风格字符串视为字符数组,并在到达 null 终止符之前执行操作。
本文将介绍 <cstring> 库提供的一些常用复制函数及它们的用法。
1.头文件
使用<cstring> 库里的复制函数,要先包含头文件:
#include <cstring>2.<cstring> 头文件的函数
2.1 复制函数
复制函数用于操作和复制 C 风格字符串或内存块。每个函数都有其自己的用途,具体取决于是否使用以 null 结尾的字符串或原始内存块。
常用的 C++ <cstring> 复制函数如下所示,以及它们的描述。
| 1 | memcpy 将一个缓冲区复制到另一个缓冲区。 |
| 2 | memmove 更安全的将一个缓冲区移动到另一个缓冲区。 |
| 3 | strcpy 用于将一个字符串复制到另一个字符串。 |
| 4 | strncpy 用于将一个字符串中一定数量的字符复制到另一个字符串。 |
2.1.1 memcpy
C 库函数 memcpy() 从一个存储区复制指定数量个字节到另一个存储区。
在下面的示例中,我们将一个字符串复制到另一个字符串。
const char b[50] = "Hello World!"; char a[50]; memcpy(a, b, strlen(b)+1); //strlen()求一个字符串的长度(字符数) printf("%s\n", a);输出:
Hello World!
2.1.2 memmove
C 库函数memmove() 在重叠内存块这方面比 memcpy() 更安全。
如果目标区域和源区域有重叠的话,memmove() 能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,复制后源区域的内容会被更改。
如果目标区域与源区域没有重叠,则和 memcpy() 函数功能相同。
看下面的示例:
char a[20] = "old"; const char b[] = "new"; printf("1.\na : %s\nb : %s\n\n\n", a, b); memmove(a, b, strlen(b)+1); //strlen()函数求一个字符串的长度(字符数) printf("2.\na : %s\nb : %s\n", a, b);输出:
1.
a : old
b : new
2.
a : new
b : new
2.1.3 strcpy
C 库函数 strcpy() 把字符串复制到目标数组,返回一个指向最终目标数组的指针。
注意:如果目标数组不够大,而源字符串的长度又太长,可能会造成缓冲溢出的情况。
看下面的示例:
char a[40]; char b[] = "Hello World!"; strcpy(a, b); printf("%s\n", a);输出:
Hello World!
2.1.4 strncpy
C 库函数 strncpy() 把字符串复制到目标数组,且需指定最多复制的字符数量。当源字符串的长度小于最多复制的字符数量时,剩余部分将用空字节填充。
因其有数量限制和自动填充功能,所以常被用作strcpy()函数的代替方案。
看下面的示例:
char a[15]; char b[40]; memset(b, '\0', sizeof(b)); strcpy(a, "Hello World!"); strncpy(b, a, 12); printf("%s\n", b);输出:
Hello World!
2.1.5 关键注意事项
- 安全性:
strcpy易引发溢出,优先使用strncpy或检查目标缓冲区大小。 - 性能:
memcpy效率最高,但不适用于重叠内存。 - 终止符:所有函数均依赖
'\0'判断字符串结束,需确保正确处理。
2.2 连接函数
连接函数用于连接 C 风格字符串或内存块。每个函数都有其自己的用途,具体取决于是否使用以 null 结尾的字符串或原始内存块。
常用的 C++ <cstring> 连接函数如下所示,以及它们的描述。
| 1 | strcat 用于连接两个字符串。 |
| 2 | strncat 用于连接两个字符串中指定数量的字符。 |
2.2.1 strcat
C 库函数 strcat() 用于连接两个 C 风格字符串。
在下面的示例中,我们将两个 C 风格字符串连接并输出。
char a[50] = "Hello "; char b[] = "World!"; strcat(a, b); printf("%s\n", a);输出:
Hello World!
2.2.2 strncat
C 库函数 strncat() 用于连接两个 C 风格字符串中指定数量的字符。
看下面的示例:
char a[30] = "Hello "; const char *b = " World!"; strncat(a, b, 10); printf("%s\n", a);此示例展示了用 strncat() 将一个字符串的一部分追加到另一个字符串的结尾。
注意:须确保目标字符数组足够大,以容纳结果字符串和结尾的空字符。
注意事项
目标字符串 a 需要有足够的空间来容纳要拷贝的字符串。
strncat() 将a字符串最后的"\0"覆盖掉,在字符追加完成后,再追加 "\0" 。
如果参数n大于源字符串src的长度,则只会复制整个src字符串到dest的末尾;如果n小于src的长度,则只会复制前n个字符。无论哪种情况,都会在新字符串的末尾添加空字符。
与strcat的区别
strcat() 函数把源字符串整个连接到目标字符串的后面,而 strncat() 则可以指定连接源字符串前指定数量个字符。
使用 strncat()可以避免陷入死循环的可能,并且能够自由控制要增加的字符个数。
2.3 其他函数
除了复制和连接函数,C库还提供了用于比较、搜索和计算字符串长度的函数。这些函数同样是操作 C 风格字符串的基础工具。
常用的 C 库其他函数以及它们的描述如下。
| 1 | strlen 计算字符串的长度(不包括终止空字符)。 |
| 2 | strcmp 比较两个字符串。 |
| 3 | strncmp 比较两个字符串的前 n 个字符。 |
| 4 | strchr 在字符串中查找第一次出现指定字符的位置。 |
| 5 | strstr 在字符串中查找第一次出现指定子字符串的位置。 |
2.3.1 strlen
C 库函数 strlen() 用于计算字符串的长度,即从字符串开头到终止空字符('\0')之前的字符数。
看下面的示例:
#include <cstring> #include <cstdio> int main() { const char* str = "Hello, CSDN!"; size_t len = strlen(str); printf("字符串 \"%s\" 的长度是 %zu。\n", str, len); return 0; }输出:
字符串 "Hello, CSDN!" 的长度是 12。
2.3.2 strcmp
C 库函数 strcmp() 用于比较两个字符串。它按字典顺序逐个字符比较,直到遇到不同的字符或遇到终止空字符为止。
返回值:
- 若 str1 小于 str2,返回负值。
- 若 str1 等于 str2,返回 0。
- 若 str1 大于 str2,返回正值。
看下面的示例:
#include <cstring> #include <cstdio> int main() { const char* str1 = "apple"; const char* str2 = "banana"; int result = strcmp(str1, str2); if (result < 0) { printf("\"%s\" 小于 \"%s\"\n", str1, str2); } else if (result > 0) { printf("\"%s\" 大于 \"%s\"\n", str1, str2); } else { printf("\"%s\" 等于 \"%s\"\n", str1, str2); } return 0; }输出:
"apple" 小于 "banana"
2.3.3 strncmp
C 库函数 strncmp() 用于比较两个字符串的前 n 个字符。与 strcmp() 类似,但只比较指定数量的字符。
看下面的示例:
#include <cstring> #include <cstdio> int main() { const char* str1 = "abcdef"; const char* str2 = "abcxyz"; int result = strncmp(str1, str2, 3); // 比较前3个字符 if (result == 0) { printf("前3个字符相同。\n"); } else { printf("前3个字符不同。\n"); } return 0; }输出:
前3个字符相同。
2.3.4 strchr
C 库函数 strchr() 在字符串中查找第一次出现指定字符的位置,并返回指向该位置的指针。如果未找到,则返回空指针(NULL)。
看下面的示例:
#include <cstring> #include <cstdio> int main() { const char* str = "Hello, World!"; char ch = 'W'; const char* result = strchr(str, ch); if (result != NULL) { printf("字符 '%c' 在字符串中第一次出现的位置是:%ld\n", ch, result - str); } else { printf("未找到字符 '%c'\n", ch); } return 0; }输出:
字符 'W' 在字符串中第一次出现的位置是:7
2.3.5 strstr
C 库函数 strstr() 在字符串中查找第一次出现指定子字符串的位置,并返回指向该位置的指针。如果未找到,则返回空指针(NULL)。
看下面的示例:
#include <cstring> #include <cstdio> int main() { const char* str = "C++ programming is fun!"; const char* substr = "programming"; const char* result = strstr(str, substr); if (result != NULL) { printf("子字符串 \"%s\" 在字符串中第一次出现的位置是:%ld\n", substr, result - str); } else { printf("未找到子字符串 \"%s\"\n", substr); } return 0; }输出:
子字符串 "programming" 在字符串中第一次出现的位置是:4
关键注意事项
- 安全性:
strcmp和strncmp不会修改字符串内容,相对安全。 - 性能:
strlen需要遍历整个字符串直到遇到 '\0',时间复杂度为 O(n)。 - 空指针检查:使用
strchr和strstr前应确保字符串不为空,使用后应检查返回值是否为 NULL。 - 终止符检查(重要!):使用的 C 风格字符串应确保以 '\0' 结尾,否则函数可能会越界访问内存,导致未定义行为、程序崩溃或安全漏洞。
3.总结
通过合理选择函数,可以高效、安全地在 C++中 操作 C 风格字符串。
温馨提示:请留下点赞!