字符/字符串函数
01.求字符串长度
1.1strlen()函数原型
- size_t strlen(const char *str);
复制代码 参数: str:要计算长度的字符串的首地址
功能: 从给定内存地址开始扫描,直到遇到第一个'\0'竣事符为止,统计这之间的字符数目。
返回值: 返回一个 size_t 类型的值,表示字符串中的字符数。(不包括空字符’\0’)
1.2模拟实现my_strlen()
- //非递归求字符串长度
- int My_Strlen(char* str){
- int count = 0;//临时变量
- while (*str!='\0'){//传递的是字符串首地址,,解引用即可
- count++;
- str++;//找下一个字符
- }return count;
- }
- //递归
- int My_Strlen(char* str){
- if (*str!='\0'){
- return 1 + My_Strlen(str + 1);//加一个字符串的长度
- }return 0;
- }
- int main(){
- char arr[] = "zbc";//['z','b','c','\0']包括'\0'
- int len = My_Strlen(arr);//传递的是数组的首地址过去
- return 0;
- }
复制代码 1.3 sizeof()简述
- sizeof 操作符在编译时求值,不会引起运行时开销
- sizeof 可以用于任何数据类型,包括用户自界说类型
- sizeof 的返回值类型是 size_t(无符号整数类型)
- sizeof 可以利用两种语法情势: sizeof(类型名) 或 sizeof 表达式
1.4 深入解析 strlen() 与 sizeof ()的区别
一般情况下数组名表示首地址的地址,但是有特别情况sizeof(数组名)和&数组名(取出整个数组的地址,是一个随机值)表示的是整个数组的大小。strlen()计算字符数组的字符数,以"\0"为竣事判定,不计算为’\0’的数组元素。 而sizeof计算数据(包括数组、变量、类型、布局体等)所占内存空间,用字节数表示。
示例代码:- char text[100] = "Programming";
- printf("strlen: %zu\n", strlen(text)); // 11
- printf("sizeof: %zu\n", sizeof(text)); // 100
- -----
- char *ptr = "Hello World";
- printf("strlen: %zu\n", strlen(ptr)); // 11
- printf("sizeof: %zu\n", sizeof(ptr)); // 4或8(指针大小)
复制代码 内存布局:- 示例字符串"Hello"的内存表示:
- +-----+-----+-----+-----+-----+-----+
- | 'H' | 'e' | 'l' | 'l' | 'o' | '\0'|
- +-----+-----+-----+-----+-----+-----+
- 0x00 0x01 0x02 0x03 0x04 0x05
-
- strlen结果:5(0x00-0x04)
- sizeof结果:6(整个数组大小)
复制代码 02.长度不受限定的字符串函数
- char *strcpy(char *dest, const char *src);//将源字符串复制到目标串中,并在目标串末尾添加空字符'\0'。
复制代码 2.1 strcpy()字符串拷贝
参数: dest: 目标字符串地址 src: 源字符串地址
功能: 将 src 指向的字符串(包括空字符 \0)复制到 dest 指向的内存中。
返回值: 返回 dest 的地址
2.1.1 模拟实现my_strcpy()
- char* My_Srecpy(char* dest, const char* src){
- char *ret = dest;
- assert(dest != NULL);
- assert(src != NULL);
- while(*dest != *src){
- dest++;
- src++;
- }
- return ret;
- }
复制代码
- char* strcat(char* dest, const char* src);
复制代码 2.2 strcat ()字符串拼接
参数: dest: 目标字符串地址src: 源字符串地址
功能: 将 src 指向的字符串追加到 dest 的末尾(覆盖 dest 的 \0)。
返回值: 返回 dest的地址
注意: 两常量字符串不能拼接说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。在str为NULL的情况下调用strcpy和strcat,试图往空指针指向的内存空间写入数据,这会导致步伐崩溃。
2.2.1 模拟实现My_Strcat()
- char* My_Strcat(char* dest, const char* src){
- char *ret = dest;
- assert(dest != NULL);
- assert(src != NULL);
- while(*dest !=NULL){
- dest++;
- }
- while((*dest++ = *src++)){
- ;
- }
- return ret;
- }
复制代码
- int strcmp(const char* str1, const char* str2);
复制代码 2.3 strcmp()字符串比力
参数: str1: 字符串1地址;str2: 字符串2地址
功能: 比力 str1 和 str2 的字典次序(按ASCII值逐字符比力)。
返回值: 返回整数:(str1 < str2),返回负值,(str1 == str2),返回0,若 (str1 > str2),返回正值
2.3.1 模拟实现My_Strcmp()
- int strcmp(const char* str1, const char* str2){//比较的是ascii码值,需要转换,逐字符比较
- int ret = 0;
- assert(dest != NULL);
- assert(src != NULL);
- while(*str1 != '\0' && *str2 != '\0' && *str1 == *str2){
- srt1++;
- str2++;
- }
- return (*str1 - *str2)
- }
复制代码 03.长度受限定的字符串介绍
- char *strncpy(char *dest, const char *src, size_t n);
复制代码 3.1 strncpy ()字符串n拷贝
参数:
dest:目标字符串的地址,它需要有足够空间容纳源字符串n字符和空字符’\0’
src: 源字符串的地址,以’\0’竣事。
n: 需要复制的字节数
功能: strncpy 将 src 的前 n 个字符复制到 dest:若 src 长度不足 n,剩余部门用 \0 填充;若 src 长度 ≥ n,则只复制前 n 个字符且不主动补 \0,需手动添加以确保字符串合法。
返回值: 返回指向目标字符串的dest 指针。
注意:
- dest 必须足够大(至少 n 字节),否则可能溢出。
- 不会主动补 \0(当 n ≤ strlen(src) 时),需手动处理:
- 性能较低(如果 n 远大于 strlen(src),会填充大量 \0)。
- 不适合直接用于字符串操作(除非手动处理 \0)。
代码示例:- int main() {
- char dest[10];
- const char *src1 = "Hello";
- const char *src2 = "World12345";
- // 当 src < n(自动补 \0)
- strncpy(dest, src1, 10);
- printf("Case 1: %s\n", dest); // 输出 "Hello"(后面填充 \0)
- // 当 src ≥ n(不补 \0)
- strncpy(dest, src2, 5);
- dest[5] = '\0'; // 手动补余 \0
- printf("Case 2: %s\n", dest); // 输出 "World"
- return 0;
- }
复制代码
- char *strncat(char *dest, const char *src, size_t n);
复制代码 3.2 strncat ()字符串n拼接
参数:
dest:目标字符串的地址,它需要有足够空间容纳拼接后的字符串和空字符’\0’
src:源字符串的指针的首地址
n:最多追加的字符数(不包括主动添加的 \0)
功能: 将 src 的前 n 个字符(或遇到 \0 时停止)追加到 dest 的末尾,并主动在最终结果后补 \0。能够防止dest溢出,安全拼接字符串(比 strcat 更安全)。
**返回值:**返回指向目标字符串的dest 指针。
注意:
- dest 必须有足够的剩余空间(至少 strlen(dest) + n + 1)。
- dest 必须以\0开头(否则行为未界说)。
- n 仅限定 src 的字符数,strncat 始终会补 \0(即使 n 个字符后没有 \0)。
- 不会检查 dest 缓冲区是否足够大,需步伐员自行确保。
代码示例:- int main(){
- char dest[20] = "Hello";
- const char *src = ", World!";
- strncat(dest, src, 5); // 只追加 ", Wor"(5 个字符)
- printf("%s\n", dest); // 输出 "Hello, Wor"(自动补 \0)
- return 0;
- }
复制代码
- int strncmp(const char *s1, const char *s2, size_t n);
复制代码 3.3 strncmp ()字符串n比力
参数:
s1:要比力的第一个字符串
s2:要比力的第二个字符串
n:最多比力的字符数(比力前 n 个字符)
功能: 逐字符比力 str1 和 str2 的前 n 个字符(或直到遇到 \0)。
返回值:
- 前n个字符相同 → 返回0
- 比力中s1字符 < s2字符 → 返回负值
- 比力中s1字符 > s2字符 → 返回正值
注意:
- 不会主动检查字符串长度,n 不可超过缓冲区大小。
- 遇到 \0 会提前终止比力(即使 n 未用完)。
- 不适用于非字符串数据(如二进制数据,应利用 memcmp)。
代码示例:- int main() {
- const char *s1 = "Hello";
- const char *s2 = "Hellx";
- const char *s3 = "Ha";
- printf("strncmp(s1, s2, 4): %d\n", strncmp(s1, s2, 4)); // 0
- printf("strncmp(s1, s2, 5): %d\n", strncmp(s1, s2, 5)); //-11 <0('o' < 'x')
- printf("strncmp(s1, s3, 2): %d\n", strncmp(s1, s3, 2)); // 4 >0('e' > 'a')
- return 0;
- }
复制代码 04.字符串查找
- char *strstr(const char *main_str, const char *sub_str);
复制代码 4.1 strstr()字符串匹配
参数:
功能: 在主串中查找子串首次出现的位置,返回指向该位置的指针;若未找到,返回NULL。 具体实现可接纳暴力算法(逐字符匹配)和kmp算法(优化查找)
返回值:
- 找到子串时:返回子串在haystack中的起始地址,后续字符可通过指针访问。
- 未找到子串时:返回NULL。
- char str = "abcdefg";
- char *result = strstr(str, "cde");
- printf("%s\n", result); // 输出:cdefg
复制代码
- char *strtok(char *str, const char *sep);
复制代码 4.2 strtok()字符串切割
参数: str是原字符串,sep是分隔符字符串(集合)
功能: 字符串切割,按照 sep字符串(可称为集合)指向的字符串中的字符,切割 指向的字符串。其实就是在 str 指向的字符串中发现了 sep字符串中的字符,就将其变成\0调用一次strtok 只切割一次,切割一次之后,再去切割的时间strtok 的第一个参数传NULL,意思是接着上次切割的位置继续切下去。
注意: 如果 str字符串中出现了连续的几个 sep,中的字符,则只将第一个字符变成”\0
返回值: 返回的是切出来的字符串的首地址- charstr[100]="lucy:yuxin,hanbing,xiaoyang:xueyang,zhanghu:yongheng";
- char *p[8];
- int i=0,j;
- printf("str:号s\n",str);
- p[i]= strtok(str,",:;");//首次切割返回的是lucy\0,把:替换成了'\0'
- while (p[i]!-NULL){
- i++:
- p[i]=strtok(NULL,".:;");//第二次切割(比较特殊)开始第一个参数传NULL告诉它我从上一个被置为'\0'的位置开始切割
- }
- for (j=0 ;j<i;j++)
- printf("p[各d]:号s\n",j,p[j]);
复制代码 05.错误信息报告
- char *strerror(int errnum);
复制代码 5.1 strerror()
参数: errnum错误码
这个错误码一般传递的是 errno 这个变量的值,在C语言有一个全局的变量叫: errno ,当库函数的调用发生错误的时间,就会把本次错误的错误码存放在 errno 这个变量中,利用这个全局变量需要包含一个头文件errno.h 。
功能:
- C 尺度库中用于将错误码转换为可读错误信息的函数。strerror 函数可以通过参数部门的 errnum 表示错误码,得到对应的错误信息,而且返回这个错误信息字符串首字符的地址。
- strerror 函数只针对尺度库中的函数发生错误后设置的错误码的转换。
返回值: 函数返回通过错误码得到的错误信息字符串的首字符的地址,
06.字符操作
…
07.内存操作函数
- void *memcpy(void *dest, const void *src, size_t count);
复制代码 7.1 memcpy()内存拷贝
参数: dest目标地址,src源地址,count拷贝字节数
功能: 将src指向的内存块逐字节复制count个字节到dest
注意:
- 禁止内存重叠:dest和src所指空间重叠会导致未界说行为。
- 目标空间足够大
模拟实现:- void* my_memcpy(void* dest, const void* src, size_t count) {
- assert(dest && src);
- while(count--){
- *(char *)dest=*(char *)src;
- dest=*(char *)dest+1;
- src=*(char *)src+1;
- }
- return dest;
- }
复制代码 利用场景:- int src[5] = {1, 2, 3, 4, 5};
- int dest[5];
- memcpy(dest, src, sizeof(src)); //拷贝20字节
复制代码
- void *memmove(void *dest, const void *src, size_t count);
复制代码 7.2 memmove() 安全拷贝
参数: dest目标地址,src源地址,count拷贝字节数
功能: 与memcpy类似,但允许源和目标内存块重叠,通过判定 src 和 dest 的位置关系,决定拷贝方向(从前向后或从后向前)
模拟实现:- void* my_memmove(void* dest, const void* src, size_t n) {
- if (dest == NULL || src == NULL) return NULL;
- char* d = (char*)dest;
- const char* s = (const char*)src;
- if (d < s) { // 目的串小于原串,从前向后拷贝
- for (size_t i = 0; i < n; i++) {
- d[i] = s[i];
- }
- } else {
- for (size_t i = n; i > 0; i--) {
- d[i-1] = s[i-1];
- }
- }
- return dest;
- }
复制代码 利用场景:- char str[20] = "hello, world!";
- memmove(str + 7, str + 12, 5); // 将 ", world!" 的 "world!" 前移
- // 结果:str 变为 "hello, !"
复制代码
- void *memset(void *dest, int value, size_t count);
复制代码 7.3 memset() 内存填充
参数: dest目标地址,value填充值,count拷贝字节数
功能: 将 src 指向的内存块的前 n 个字节设置为 value 的值
模拟实现:- void* my_memset(void* dest, int value, size_t count) {
-
- return ptr;
- }
复制代码 利用场景:- //数组元素置位0
- int arr[10];
- memset(arr, 0, sizeof(arr));
复制代码
- int memcmp(const void *ptr1, const void *ptr2, size_t count);
复制代码 7.4 memcmp()内存比力
参数: ptr1内存快1,ptr2内存快2,count拷贝字节数
功能: 比力(逐字节比力,遇到\0不终止)两个内存块的前count个字节
返回值: 相等返回0,否则返回顾个不匹配字节的差值
模拟实现:- int my_memcmp(const void* ptr1, const void* ptr2, size_t count) {
- const char* p1 = (const char*)ptr1;
- const char* p2 = (const char*)ptr2;
- for (size_t i = 0; i < count; i++) {
- if (p1i != p2i) {
- return p1i - p2i;
- }
- }
- return 0;
- }
复制代码 利用场景:- // 比较两个字符串
- unsigned char buf1[] = "dsahihdaoDD";
- unsigned char buf2[] = "dsahihdaoDd";
- int result = memcmp(buf1, buf2, sizeof(buf1)); //返回负数
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
|