2025年C语言字符串函数的详解

C语言字符串函数的详解一 字符串具体有哪些 求字符串的长度 strlen 长度不受限制的字符串函数 strcpy strcat strcmp 长度受限制的字符串函数介绍 strncpy strncat strncmp 字符串查找 strstr strtok 错误信息报告 strerror 字符操作 内存操作函数 memcpy memmove memset memcmp 二

大家好,我是讯享网,很高兴认识大家。

一.字符串具体有哪些

求字符串的长度
strlen
长度不受限制的字符串函数
strcpy
strcat
strcmp
长度受限制的字符串函数介绍
strncpy
strncat
strncmp
字符串查找
strstr
strtok
错误信息报告
strerror

字符操作

内存操作函数
memcpy
memmove
memset
memcmp

二.具体的函数的介绍

1.strlen

size_t strlen ( const char * str ); /* 具体语法 字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包 含 '\0' )。 size_t strlen ( const char * str ); 参数指向的字符串必须要以 '\0' 结束。 注意函数的返回值为size_t,是无符号的( 易错 ) */ 
讯享网
具体的使用
讯享网int main() { 
    char arr[] = "abc\0"; printf("%d\n", strlen(arr)); char brr[] = { 
    'a','b','c','\0'}; printf("%d\n",strlen(brr)); return 0; 
模拟实现strlen
size_t my_strlen(const char* str) { 
    assert(str); const char* start = str; const char* end = str; while (*end != '\0') { 
    end++; } return end - start; } int main() { 
    char arr[] = "abcdef"; int len = my_strlen(arr); printf("%d\n", len); return 0; } 

2.长度受限制的字符串函数介绍

拷贝字符串
strcpy
剪切字符串
strcat
比较字符串
strcmp
下面让我一个一个去看这些方法的用法

  • strcpy
讯享网char* strcpy(char * destination, const char * source ); /* Copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point). 源字符串必须以 '\0' 结束。 会将源字符串中的 '\0' 拷贝到目标空间。 目标空间必须足够大,以确保能存放源字符串。 目标空间必须可变。 */ 

具体用法

int main() { 
    char arr[10] = "xxxxxxxxx"; const char* p = "abcdef"; char arr2[] = { 
    'b', 'i', 't','\0'}; strcpy(arr, p); strcpy(arr, arr2); printf("%s\n", arr); return 0; } 

这里我们监视变量就可以看出它是如何复制字符串的
在这里插入图片描述

char* my_strcopy(char* dest,const char*src) { 
    assert(dest); assert(src); char* ret = dest; while (*dest++ = *src++) { 
    ; } return dest; } int main() { 
    char arr1[20] = "abc"; char arr2[] = "helloworld"; my_strcopy(arr1, arr2); printf("%s\n", arr1); return 0; } 

strcat函数的具体说明
这个函数以"\0"为标识的 进行追加的。

char * strcat ( char * destination, const char * source ); 源字符串必须以 '\0' 结束。 目标空间必须有足够的大,能容纳下源字符串的内容。 目标空间必须可修改。 

具体的用法

追加字符串 int main() { 
    char arr1[20] = "hello"; char arr2[20] = "world"; strcat(arr1,arr2); printf("%s\n",arr1); return 0; 

我们看图说话,目前看来可以说是以“\0”为追加的。
在这里插入图片描述

strcat的模拟实现

char* my_strcat(char*dest ,const char*src) { 
    //1.找目标函数的\0 char* cur = dest; while (*cur!='\0') { 
    cur++; } //2..拷贝源头数据到\0之后 while (*cur++ = *src++) { 
    ; } } int main() { 
    char arr1[20] = "hello \0xxxxxxxxxx"; char arr2[] = "world"; my_strcat(arr1,arr2); printf("%s\n",arr1); return 0; } 

strcmp 字符串的比较
这个函数就十分的简单,我就简单的说明一下,这个字符串比较函数,实际上就是一个一个字节字节的比对。
具体的使用

/* 实际上是一个字节一个字节的比较 实际上比较对应位置上字符的大小,而并非长度 */ int main() { 
    char arr1[] = "abcdef"; char arr2[] = "abq"; int ret = strcmp(arr1,arr2); printf("%d\n",ret); return 0; } 

具体的函数实现

int my_strcmp(const char* s1, const char* s2) { 
    assert(s1 && s2); while (*s1 == *s2) { 
    if (*s1=='\0') { 
    return 0; } s1++; s2++; } if (*s1 > *s2) { 
    return 1; } else { 
    return -1; } } //字符串比较函数的实现 int main() { 
    char arr1[] = "abc"; char arr2[] = "abq"; int ret=my_strcmp(arr1,arr2); if (ret > 0) { 
    printf("arr1>arr2"); } else if (ret < 0) { 
    printf("arr1<arr2"); } else { 
    printf("arr1==arr2"); } return 0; } 

这三组函数,长度受限制,顾名思义,我们做操作的时候,可以指定数量
strncpy

char * strncpy ( char * 目标, const char *, size_t num ); 从字符串中复制字符 将source的前num个字符 复制到destination。如果在复制num个字符之前找到源C 字符串的结尾(由空字符表示) ,则用零填充目标,直到总共写入了num个字符。如果source长于num ,则不会在目标 末尾隐式附加空字符。因此,在这种情况下,目的地不应被视为以空结尾的 C 字符串(这样读取它会溢出)。目的地和 
int main() { char arr1[20] = "abcdefghi"; char arr2[] = "xxxx"; strncpy(arr1, arr2, 8); printf("%s\n", arr1); return 0; } 

strncat

 int main() { 
    char arr1[20] = "abcdef\0"; char arr2[] = "xyz"; strncat(arr1, arr2, 2); printf("%s\n", arr1); return 0; } 

strncmp

int main() { 
    int ret = strncmp("abcdef", "abc", 4); printf("%d\n", ret); return 0; } 

3.字符串查找

strstr

char * strstr ( const char *str1, const char * str2); 定位子串 返回指向 str1 中第一次出现str2的指针,如果str2不是 str1 的一部分,则返回空指针。 匹配过程不包括终止的空字符,但它会停在那里。 

这里大概的意思是,记录字串第一次出现的位置
具体用法

int main() { 
    char arr1[] = "abcdef"; char arr2[] = "bcd"; char* p = strstr(arr1, arr2); if (p == NULL) { 
    printf("不存在"); } else { 
    printf("%s\n",p); } } 

strstr 模拟实现
这个方法不好理解,我画个图大家理解一下

char* my_strstr(const char* str1, const char* str2) { 
    const char* s1 = str1; const char* s2 = str2; const char* p = str1; if (*str2 == '\0') { 
    return str1; } while (*p) { 
    s1 = p; s2 = str2; while (*s1 != '\0' && *s2 != '\0' && (*s1 == *s2)) { 
    s1++; s2++; } if (*s2 == '\0') { 
    return (char*)p;//找到了 } p++; } return NULL;//找不到子串 } int main() { 
    char arr1[] = "abcdefabcdef"; char arr2[] = "fab"; char* p = my_strstr(arr1, arr2); if (p == NULL) { 
    printf("不存在\n"); } else { 
    printf("%s\n", p); } return 0; } 

3.内存操作函数
memcpy

 memcpy 的函数用法 int main() { 
    int arr[] = { 
   1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int arr2[10] = { 
    0 }; memcpy(arr2, arr, 20); float arr1[] = { 
    1.0f,2.0f,3.0f,4.0f }; float arr2[] = { 
    0.0 }; return 0; } 

具体模拟实现

// 如何自己实现memcpy void* my_memcpy(void* dest,void* src,size_t num) { 
    assert(dest); assert(src); void* ret = dest; while (num--) { 
    *(char*)dest = *(char*)src; dest = (char*)dest + 1; src = (char*)src + 1; } return ret; } int main() { 
    int arr[] = { 
   1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int arr2[10] = { 
    0 }; my_memcpy(arr2, arr, 20); int i = 0; for (i = 0; i < 10; i++) { 
    printf("%d",arr2[i]); } float arr3[] = { 
    1.0f,2.0f,3.0f,4.0f }; float arr4[] = { 
    0.0 }; my_memcpy(arr4, arr3, 20); return 0; } 

这里我们引入一个问题,如果我们自己拷贝自己的话
是否会成功吗?
试一试就知道了

int main() { 
    int arr1[] = { 
    1,2,3,4,5,6,7,8,9,10 }; memcpy(arr1 + 2, arr1, 20); //memmove(arr1+2, arr1, 20); //int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; //int arr2[10] = { 0 }; //my_memcpy(arr2, arr1, 20); int i = 0; for (i = 0; i < 10; i++) { 
    printf("%d ", arr1[i]); } } 

运行截图
在这里插入图片描述
你看,我们这里,就出现了自己拷贝自己的问题,
简单来说,就是,我们正常拷贝的时候,会出现以下情况
在这里插入图片描述

所以我们拷贝数据有时候不能从前往后拷贝,有时候会覆盖,这样我们可以考虑从后向前拷贝,我把这样的情况分为以下三种情况
在这里插入图片描述

改进之后的代码,如下

void* my_memcpy(void* dest,void* src,size_t num) { 
    assert(dest); assert(src); void* ret = dest; if (dest < src) { 
   //前->后 while (num--) { 
    *(char*)dest = *(char*)src; dest = (char*)dest + 1; src = (char*)src + 1; } } else { 
    //从后向前 while (num--) { 
    *((char*)dest + num) = *((char*)src + num); } } return ret; } int main() { 
    int arr[] = { 
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; my_memcpy(arr+2, arr, 20); int i = 0; for (i = 0; i < 10; i++) { 
    printf("%d ",arr[i]); } return 0; } 

memmove

void * memmove ( void * dst, const void * src, size_t count) { 
    void * ret = dst; if (dst <= src || (char *)dst >= ((char *)src + count)) { 
    /* * Non-Overlapping Buffers 比特就业课-专注IT大学生就业的精品课程 比特主页:https://m.cctalk.com/inst/s9yewhfr 比特就业课 本章完 * copy from lower addresses to higher addresses */ while (count--) { 
    *(char *)dst = *(char *)src; dst = (char *)dst + 1; src = (char *)src + 1; } } else { 
    /* * Overlapping Buffers * copy from higher addresses to lower addresses */ dst = (char *)dst + count - 1; src = (char *)src + count - 1; while (count--) { 
    *(char *)dst = *(char *)src; dst = (char *)dst - 1; src = (char *)src - 1; } } return(ret); } 

memset

具体用法

int main() { 
    int arr[] = { 
    1,2,3,4,5 }; memset(arr, 0, 8); return 0; } 

memcmp

int memcmp ( const void * ptr1, const void * ptr2, size_t num ); 

具体用法

memcmp的使用 int main() { 
    int arr2[] = { 
    1,2,3,0,0 }; int arr1[] = { 
    1,2,3,4,5 }; int ret=memcmp(arr1, arr2,12); printf("%d\n",ret); return 0; } 

模拟实现

void * memcpy ( void * dst, const void * src, size_t count) { 
    void * ret = dst; assert(dst); assert(src); /* * copy from lower addresses to higher addresses */ while (count--) { 
    *(char *)dst = *(char *)src; dst = (char *)dst + 1; src = (char *)src + 1; } return(ret); } 
小讯
上一篇 2025-01-05 14:48
下一篇 2025-04-11 18:49

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/68070.html