目录

一、strlen函数

1.strlen函数的使用

2.strlen函数的模拟实现

二、strcpy函数

1.strcpy函数的使用

2.strcpy函数的模拟实现

三、srtcat函数

1.strcat函数的使用

2.strcat函数的模拟实现

四、strcmp函数

1.strcmp函数的使用

2.strcmp函数的模拟实现

五、strncpy函数

1.strncpy函数的使用

2.strncpy函数的模拟实现

六、strncat函数

1.strncat函数的使用

2.strncat函数的模拟实现

七、strncmp函数

1.strncmp函数的使用

2.strncmp函数的模拟实现

八、strstr函数

1.strstr函数的使用

2.strstr函数的模拟实现

九、strtok函数

十、strerror函数

十一、字符分类与字符转换函数

1.字符分类函数

2.字符转换函数

十二、memcpy函数

1.memcpy函数的使用

2.memcpy函数的模拟实现

十三、memmove函数

1.memmove函数的使用

2.memmove函数的模拟实现


下面的这些函数都需要引用string.h的头文件

一、strlen函数

1.strlen函数的使用

size_t strlen(const char* str);

  • 字符串以’\0′ 为结束标志,strlen函数返回的是在字符串中 ‘\0′ 前面出现的字符个数(不包含’\0’ )。
  • 参数指向的字符串必须要以 ‘\0’ 结束。
  • 注意函数的返回值为size_t,是无符号的整数( 易错 )
#include#includeint main(){char a[10] = "abcdef";int ret = strlen(a);printf("%d", ret);return 0;}//结果:6

2.strlen函数的模拟实现

#includesize_t my_strlen(char* arr){size_t ret = 0;while (*arr != '\0'){ret++;arr++;}return ret;}int main(){char a[10] = "abcdef";int ret = my_strlen(a);printf("%d", ret);return 0;}//结果:6

二、strcpy函数

1.strcpy函数的使用

char* strcpy(char * destination, const char * source );

  • 源字符串必须以 ‘\0’ 结束。
  • 会将源字符串中的 ‘\0’ 拷贝到目标空间。
  • 目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可变。
#include#includeint main(){char arr1[10] = "abcdefhij";char arr2[10] = "xxxxxx";strcpy(arr2, arr1);printf("%s", arr2);return 0;}//结果:abcdefhij

2.strcpy函数的模拟实现

#include#include#includechar* my_strcpy(char* dest, const char* src) {assert(dest && src);char* p = dest;while(*src != '\0'){*dest = *src;dest++;src++;}return p;}int main(){char arr1[10] = "abcdefhi";char arr2[10] = "xxxxxx";my_strcpy(arr2, arr1);printf("%s", arr2);return 0;}//结果:abcdefhi

我们将指针前进与赋值合在一起,两个指针先解引用,然后赋值,然后指针再向前移动,当遇到解引用的元素为\0时,dest被赋值为\0,这个表达式的值为0直接跳出循环

#include#includechar* my_strcpy(char* dest, const char* src){assert(dest && src);char* p = dest;while (*dest++ = *src++);return p;}int main(){char arr1[10] = "abcdefhi";char arr2[10] = "xxxxxx";my_strcpy(arr2, arr1);printf("%s", arr2);return 0;}

三、srtcat函数

1.strcat函数的使用

char* strcat(char* destination, const char* source);

  • 源字符串必须以 ‘\0’ 结束。
  • 目标空间必须有足够的大,能容纳下源字符串的内容。
  • 目标空间必须可修改。
  • 字符串自己给自己追加,/0已经被改掉了,这个程序会崩溃
#include#includeint main(){char arr1[20] = "hello ";char arr2[20] = "world";strcat(arr1, arr2);printf("%s", arr1);return 0;}//结果:hello world

2.strcat函数的模拟实现

#include#includechar* my_strcat(char* dest, const char* src){assert(dest && src);char* p = dest;while (*dest != '\0'){dest++;//查找待加长字符串\0的位置}*dest = *src;//加长字符串的\0赋值成非\0的字符,这里也可以使用dowhile循环while (*dest++ = *src++);//strcpy函数模拟实现return p;}int main(){char arr1[20] = "hello ";char arr2[20] = "world";my_strcat(arr1, arr2);printf("%s", arr1);return 0;}//结果:hello world

四、strcmp函数

1.strcmp函数的使用

int strcmp(const char* str1, const char* str2);

  • 这个函数会从两个字符串的第一个字符开始比较,哪一个字符的ASCII码大,哪一个字符串大,如果两个字符一样,就继续比较下一个字符。
  • 第一个字符串大于第二个字符串,则返回大于0的数字
  • 第一个字符串等于第二个字符串,则返回0
  • 第一个字符串小于第二个字符串,则返回小于0的数字
#include#includeint main(){char arr1[20] = "abcdifgh";char arr2[20] = "abcdefgh";int ret = strcmp(arr1, arr2);if (ret > 0){printf("arr1>arr2");}else if (ret == 0){printf("arr1=arr2");}else{printf("arr1

2.strcmp函数的模拟实现

#include#includeint my_strcmp(const char* str1, const char* str2){assert(str1 && str2);while (*str1 == *str2 && *str1 != '\0'){str1++;str2++;}return *str1 - *str2;}int main(){char arr1[20] = "abcdefgh";char arr2[20] = "abcdefh";int ret = my_strcmp(arr1, arr2);printf("%d\n", ret);if (ret > 0){printf("arr1>arr2");}else if (ret == 0){printf("arr1=arr2");}else{printf("arr1

五、strncpy函数

1.strncpy函数的使用

char* strncpy(char* destination, const char* source, size_t num);

  • 拷贝num个字符从源字符串到目标空间。
  • 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
  • 返回的指针指向被改变的字符串的首字符地址。
#include#includeint main(){char arr1[10] = "abcedf";char arr2[10] = "xxxxxxxx";strncpy(arr2, arr1, 5);printf("%s\n", arr2);return 0;}//结果:abcedxxx

2.strncpy函数的模拟实现

#include#includechar* my_strncpy(char* dest, const char* src, size_t num){assert(dest && src);char* p = dest;while (num-- && *src != '\0'){*dest++ = *src++;}return p;}int main(){char arr1[10] = "abcedf";char arr2[10] = "xxxxxxxx";strncpy(arr2, arr1, 7);printf("%s\n", arr2);return 0;}

六、strncat函数

1.strncat函数的使用

char* strncat(char* destination, const char* source, size_t num);

  • 可以对字符串加长限定数目的字符
  • 返回的指针指向被改变的字符串的首字符地址
#include#includeint main(){char arr1[20] = "hello ";char arr2[20] = "world";char* ret = strncat(arr1, arr2, 3);printf("%s", ret);return 0;}//结果:hello wor

2.strncat函数的模拟实现

#include#includechar* my_strncat(char* dest, const char* src, size_t num){assert(dest && src);char* p = dest;while (*dest != '\0'){dest++;}*dest = *src;while (num-- && *src != '\0'){*dest++ = *src++;}return p;}int main(){char arr1[12] = "hello ";char arr2[20] = "world";char* ret = my_strncat(arr1, arr2, 3);printf("%s", ret);return 0;}

七、strncmp函数

1.strncmp函数的使用

int strncmp(const char* str1, const char* str2, size_t num)

  • 这个函数会从两个字符串的第一个字符开始比较,哪一个字符的ASCII码大,哪一个字符串大,如果两个字符一样,就继续比较下一个字符。
  • 这个函数可以比较限定数目的字符。
int strncmp(const char* str1, const char* str2, size_t num);#includeint main(){char arr1[12] = "abcdef";char arr2[20] = "abcfg";int ret = strncmp(arr1, arr2, 3);printf("%d\n", ret);if (ret > 0){printf("arr1>arr2");}else if (ret == 0){printf("arr1=arr2");}else{printf("arr1

2.strncmp函数的模拟实现

#include#includeint my_strncmp(const char* str1, const char* str2, size_t num){assert(str1 && str2);while (num-- && *str1 == *str2 && *str1 != '\0'){if (num>1){str1++;str2++;}}return *str1 - *str2;}int main(){char arr1[12] = "abcdef";char arr2[20] = "abcfg";int ret = my_strncmp(arr1, arr2, 3);if (ret > 0){printf("arr1>arr2");}else if (ret == 0){printf("arr1=arr2");}else{printf("arr1

八、strstr函数

1.strstr函数的使用

char* strstr(const char* str1, const char* str2);

  • 查找一个字符串中是否存在另一个子字符串
  • 例如:abcdef中查找bcd就是存在的,而查找acd就是不存在的
  • 返回的指针为查找到的位置的地址,比如说上面的例子中我们找到了bcd那么返回的指针就指abcdef中的那个字符b
#include#includeint main(){char arr1[30] = "Je vais bien.";char arr2[10] = "vais";char* p = strstr(arr1, arr2);printf("%s\n", p);return 0;}//结果:vais bien.

2.strstr函数的模拟实现

#include#includechar* my_strstr(const char* str1, const char* str2){char* s1 = (char*)str1;char* s2 = (char*)str2;char* cp = (char*)str1;//cp保存首字符地址assert(str1 && str2);while (*cp){s1 = cp;while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2){s1++;s2++;}if (*s2 == '\0'){return cp;}s2 = (char*)str2;cp++;//cp++可以得到原起始位置的下一个位置}return NULL;}int main(){char arr1[30] = "Je vais bien.";char arr2[10] = "vais";char* p = my_strstr(arr1, arr2);printf("%s\n", p);return 0;}

九、strtok函数

char* strtok(char* str, const char* sep);

  • 第一个数组储存待拆分字符串
  • 第二个数组储存所有的分隔符号
  • 函数会在待拆分字符串中从左到右找到一个分隔符号并将其赋值为\0
  • 返回的指针指向分割的那一部分字符串的开头,同时函数会记住原来分隔符的位置
  • 我们第一个参数传空指针即可继续分割
  • 例如:
  • 我们的数组一设置为:qwe123456789@163.com
  • 数组二设置为:.@
  • 第一次分割:qwe123456789\0163.com
  • 返回的地址指向q,内部存储的指针指向\0
  • 再次传递NULL,第二次分割:qwe123456789\0163\0com
  • 返回的地址指向1,内部存储的指针指向下一个\0
  • 以此类推,直到字符串末尾
#include#includeint main(){char arr1[30] = "qwe123456789@163.com";char arr2[10] = "@.";char* p = strtok(arr1, arr2);printf("%s\n", p);p = strtok(NULL, arr2);printf("%s\n", p);p = strtok(NULL, arr2);printf("%s\n", p);return 0;}//结果://qwe123456789//163//com

十、strerror函数

char * strerror ( int errnum );

  • 在C程序中存在一个全局变量errno,要想使用这个变量需要引用头文件errno.h
  • 当程序出现问题的时候这个变量就会存储一个对应这个错误的数字
  • 但是只有这个数字我们不知道这个错误是什么
  • 而这个函数可以根据这个errno的值找到对应的错误,返回错误内容的字符串
#include#include#includeint main(){FILE* pFile;pFile = fopen("unexist.ent", "r");if (pFile == NULL)printf("Error opening file unexist.ent: %s\n", strerror(errno));return 0;}//结果:Error opening file unexist.ent: No such file or directory

十一、字符分类与字符转换函数

1.字符分类函数

可以判断字符是否为所需要的那一种类型的字符

下面是这部分的一些函数:

  • iscntrl 任何控制字符
  • isspace 空白字符:空格‘ ’,换页‘\f’,换行'\n',回车‘\r’,制表符'\t'或者垂直制表符'\v'
  • isdigit 十进制数字 0~9
  • isxdigit 十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F
  • islower 小写字母a~z
  • isupper 大写字母A~Z
  • isalpha 字母a~z或A~Z
  • isalnum 字母或者数字,a~z, A~Z, 0~9
  • ispunct 标点符号,任何不属于数字或者字母的图形字符(可打印)
  • isgraph 任何图形字符
  • isprint 任何可打印字符,包括图形字符和空白字符

2.字符转换函数

  • 可以判断字符是否可以转化为所需要的那一种类型的字符,是则进行相应转换,不是则直接打印。
  • 对于字符串也可以对每一个字符进行相应操作。

比如:tolower()函数可以处理大写字母,返回值为小写字母,不是大写字母的字符直接返回原字符。

#include#includeint main(){char a = 'A';if (islower(a)){printf("小写字母\n");}else{printf("大写字母\n");}char b = "D";printf("%c", tolower(b));return 0;}//结果://大写字母//d

十二、memcpy函数

1.memcpy函数的使用

void * memcpy ( void * destination, const void * source, size_t num );

  • 这个函数是用于从一个地方拷贝相应字节的内容到另一个地方
  • 只能用于原空间与目标空间无重叠的情况
#include#includeint main(){int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] = { 0 };memcpy(arr2,arr1,sizeof(arr1));int i = 0;for (i=0; i<10; i++){printf("%d ", arr2[i]);}return 0;}//结果:1 2 3 4 5 6 7 8 9 10

2.memcpy函数的模拟实现

类似于模拟实现qsort,以一个字节为单位操作

#include#includevoid* my_memcpy(void* dest, const void* src, size_t num){assert(dest && src);char* s1 = dest;char* s2 = src;while (num--){*s1 = *s2;s1++;s2++;}return dest;}int main(){double arr1[10] = {1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2.0 };double arr2[10] = { 0 };my_memcpy(arr2, arr1, 80);int i = 0;for (i = 0; i < 10; i++){printf("%lf ", arr2[i]);}return 0;}

十三、memmove函数

1.memmove函数的使用

void * memmove ( void * destination, const void * source, size_t num );

  • 将一个地方的对应字节的数据拷贝放到其他地方
  • 原空间与目标空间有无重叠的情况均可
#include#includeint main(){int arr[20] = { 1,2,3,4,5,6,7,8,9,10 };memmove(arr + 2, arr, 20);int i = 0;for (i = 0;i < 10;i++){printf("%d ", arr[i]);}return 0;}//结果:1 2 1 2 3 4 5 8 9 10

2.memmove函数的模拟实现

#include#includevoid* my_memmove(void* dest, const void* src, size_t num){char* s1 = (char*)dest;char* s2 = (char*)src;if (s1 <= s2){while (num--)//dest小于src时,从前向后拷贝{*s1 = *s2;s1++;s2++;}}else{while (num--){*(s1+num) = *(s2+num);//dest大于src时,从后向前拷贝}}return dest;}int main(){int arr[20] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 };my_memmove(arr, arr+2, 20);int i = 0;for (i = 0;i < 20;i++){printf("%d ", arr[i]);}return 0;}