C语言中的字符串操作函数
盘点C语言中的字符串操作函数
1、字符串复制和连接
#include <stdio.h>
#include <string.h>
int main() {
// strcpy
char src1[] = "Hello";
char dest1[20];
strcpy(dest1, src1);
printf("strcpy: %s\n", dest1);
// strncpy
char src2[] = "World";
char dest2[20];
strncpy(dest2, src2, 3);
dest2[3] = '\0'; // 确保字符串以 null 结尾
printf("strncpy: %s\n", dest2);
// strcat
char dest3[20] = "Hello";
strcat(dest3, " World");
printf("strcat: %s\n", dest3);
// strncat
char dest4[20] = "Hello";
strncat(dest4, " World", 3);
printf("strncat: %s\n", dest4);
return 0;
}
输出:
strcpy: Hello
strncpy: Wor
strcat: Hello World
strncat: Hello Wo
注意项:
- 在使用strcat时,需要确保拼接的字符串后方有足够的内存
2、字符串比较
#include <stdio.h>
#include <string.h>
int main() {
// strcmp
char str1[] = "Hello";
char str2[] = "World";
printf("strcmp: %d\n", strcmp(str1, str2));
// strncmp
char str3[] = "Hello";
char str4[] = "Helium";
printf("strncmp: %d\n", strncmp(str3, str4, 3));
return 0;
}
输出:
strcmp: -15
strncmp: 0
strcmp 函数用于比较两个字符串,并返回一个整数值来表示它们的相对顺序。strcmp 的返回值有以下三种情况:
- 负数:如果第一个字符串小于第二个字符串,strcmp 返回一个负数。这通常是因为在比较时,第一个字符串中第一个不同的字符的 ASCII 值小于第二个字符串中对应字符的 ASCII 值。
- 零:如果两个字符串相等,strcmp 返回 0。这意味着两个字符串的长度相同,并且每个对应位置的字符都相同。
- 正数:如果第一个字符串大于第二个字符串,strcmp 返回一个正数。这通常是因为在比较时,第一个字符串中第一个不同的字符的 ASCII 值大于第二个字符串中对应字符的 ASCII 值。
3、字符串长度
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello World";
printf("strlen: %zu\n", strlen(str));
return 0;
}
输出:
strlen: 11
注意项:
- strlen是一个函数,用来查找一段内存最近的\0
- sizeof是宏定义,在预处理阶段被替换为真值
4、字符串查找
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello World";
// strchr
char *result1 = strchr(str, 'o');
if (result1) printf("strchr: %s\n", result1);
// strrchr
char *result2 = strrchr(str, 'o');
if (result2) printf("strrchr: %s\n", result2);
// strstr
char *result3 = strstr(str, "World");
if (result3) printf("strstr: %s\n", result3);
// strpbrk
char *result4 = strpbrk(str, "aeiou");
if (result4) printf("strpbrk: %s\n", result4);
// strspn
size_t len1 = strspn(str, "Helo ");
printf("strspn: %zu\n", len1);
// strcspn
size_t len2 = strcspn(str, "W");
printf("strcspn: %zu\n", len2);
return 0;
}
输出:
strchr: o World
strrchr: orld
strstr: World
strpbrk: ello World
strspn: 6
strcspn: 6
说明:
- strchr:查找字符在字符串中的第一次出现。
- strrchr:查找字符在字符串中的最后一次出现。
- strstr:查找子字符串在字符串中的第一次出现。
- strpbrk:查找字符串中任意字符集合的第一次出现。
- strspn:计算字符串前缀中包含指定字符集合的长度。
- strcspn:计算字符串前缀中不包含指定字符集合的长度。
5、字符串分割
#include <stdio.h>
#include <string.h>
int main() {
char str[] = "Hello,World,Test";
char *token = strtok(str, ",");
while (token != NULL) {
printf("strtok: %s\n", token);
token = strtok(NULL, ",");
}
return 0;
}
输出:
strtok: Hello
strtok: World
strtok: Test
说明:
strtok 函数在内部维护了一个静态指针,用于跟踪当前字符串分割的位置。这意味着第一次调用 strtok 时,它会保存字符串的起始位置,并在后续调用中继续从上次停止的位置开始处理。
strtok 的工作机制如下:
- 第一次调用:当你第一次调用 strtok(str, ",") 时,strtok 会扫描 str 直到找到第一个分隔符(在这个例子中是逗号 ,)。然后,它会用 \0 替换这个分隔符,并返回第一个标记的指针。
- 后续调用:在后续调用中,你传入 NULL 作为第一个参数,strtok 会从上次停止的位置继续扫描,寻找下一个分隔符。它会用 \0 替换找到的分隔符,并返回下一个标记的指针。
- 结束条件:当没有更多的标记可提取时,strtok 返回 NULL。
需要注意的是,由于 strtok 使用静态存储来保存状态,因此它不是线程安全的。如果你需要在多线程环境中使用类似的功能,可以考虑使用 strtok_r(POSIX 标准)或其他线程安全的字符串分割函数。 - strtok 会修改原始字符串,因此如果需要保留原始字符串不变,应该先复制一份再进行分割。
6、内存操作
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char src[] = "Hello World";
char dest[20];
// memcpy
memcpy(dest, src, strlen(src) + 1);
printf("memcpy: %s\n", dest);
// memmove (overlapping memory regions)
memmove(dest + 6, dest, strlen(dest) + 1);
printf("memmove: %s\n", dest);
// memset
memset(dest, '*', 5);
dest[5] = '\0';
printf("memset: %s\n", dest);
// memcmp
char str1[] = "abc";
char str2[] = "abd";
printf("memcmp: %d\n", memcmp(str1, str2, 3));
// memchr
char *result = memchr(src, 'W', strlen(src));
if (result) {
printf("memchr: %s\n", result);
}
// strdup
char *duplicate = strdup(src);
if (duplicate) {
printf("strdup: %s\n", duplicate);
free(duplicate); // Don't forget to free the allocated memory
} else {
printf("Failed to duplicate string.\n");
}
return 0;
}
输出:
memcpy: Hello World
memmove: Hello Hello World
memset: *****
memcmp: -1
memchr: World
strdup: Hello World
说明:
memcpy 和 memmove 都是用于在内存中复制数据的函数,但它们在处理重叠内存区域时有重要区别:
memcpy
- 用途:用于复制一个内存块的数据到另一个内存块。
- 重叠区域:memcpy 不安全用于重叠的内存区域。如果源和目标区域重叠,memcpy 的行为是未定义的。这意味着在这种情况下,memcpy 可能会导致数据损坏或其他不可预测的结果。
- 性能:通常比 memmove 更快,因为它不需要处理重叠的情况。
memmove
- 用途:同样用于复制一个内存块的数据到另一个内存块。
- 重叠区域:memmove 安全用于重叠的内存区域。它会确保在复制过程中,源数据不会被覆盖,从而保证数据的正确性。
- 性能:可能比 memcpy 稍慢,因为它需要处理重叠的情况以确保安全。
strdup
- strdup会使用malloc申请内存块,使用完成后需要释放
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。