目录
- strlen
- 函数介绍
- 模拟实现
- strcpy
- 函数介绍
- 模拟实现
- strcat
- 函数介绍
- 模拟实现
- strcmp
- 函数介绍
- 模拟实现
- strncpy
- 函数介绍
- 模拟实现
- strncat
- 函数介绍
- 模拟实现
- strncmp
- 函数介绍
- 模拟实现
- strtok
- strstr
- 函数介绍
- 模拟实现
- strerror
- perror
strlen
函数介绍
函数介绍:
字符串以’\0’作为结束标志,strlen函数返回的是在字符串中’\0’前面出现的字符个数(不包含’\0’)。
参数指向的字符串必须要以’\0’ 结束。
注意函数的返回值为size_t,是无符号的
模拟实现
计数方式:
int my_strlen(const char* str)//const修饰且在*左边,保证指向的内容不被改变
{int count = 0;assert(str);while (*str){count++;str++;}return count;
}
不创建变量方式(递归方式)
int my_strlen(const char* str)
{assert(str);if (*str == '\0')return 0;elsereturn 1 + my_strlen(str + 1);
}
指针 - 指针方式
int my_strlen(char* s)
{assert(str);char* p = s;while (*p != '\0')p++;return p - s;
}
strcpy
函数介绍
char* strcpy(char * destination, const char * source )
实现字符串拷贝,左参数是目标字符串的首地址,右参数是源字符串的首地址。
注意:
源字符串必须以‘ \0 ’ 结束。
strcpy会将源字符串的‘ \0 ’拷贝到目标空间中。
目标空间足够大,以确保能存放源字符串。
目标空间必须可变。
如果目标空间不够大,那么就会造成非法写入,然后报错。
拷贝的方法就是从源字符串的第一个字符开始一直到‘ \0 ’,如果源字符串的末尾没有以0结尾,就会一直读取,一直到0,这样就会非法访问。
模拟实现
方式1
void my_strcpy(char* str, const char* src)
{assert(str && src);while (*src){*str = *src;str++;src++;}*str = *src;
}
方式2,将方式1中while循环里面简化、
void my_strcpy(char* str, const char* src)
{assert(str && src);while (*str++ = *src++);
}
后置++,先使用再进行加操作,就算加了括号也是先使用再进行加操作。返回当前值,就是一直到str等于0的时候才停止循环。
方式3,增加返回值
char* my_strcpy(char* str, const char* src)
{char* ret = str;assert(str && src);while (*str++ = *src++);return ret;
}
strcat
函数介绍
char * strcat ( char * destination, const char * source )
字符串追加函数,在目标字符串后面追加源字符串,目标字符串的最后一个‘ \0 ’,被源字符串的第一个字符占据,追加完成以后会再新增一个‘ \0 ’。
注意:
源字符串必须以‘ \0 ’结束
目标字符串中也得有‘ \0 ’,否则没办法知道追加从哪里开始。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。
模拟实现
char* my_strcat(char* str, const char* src)
{char* ret = str;assert(str);assert(src);/*while (*str++ != '\0');在str等于0后要退出判断条件,此时会再进行一次加操作,后置加加不会因为要退出循环就不执行。str--;*/while (*str != '\0'){str++;}while (*str++ = *src++);return ret;
}
我们自己写的函数是无法自己给自己追加的,因为‘ \0 ’,被覆盖了,永远都不会遇到‘ \0 ’。但是库函数strcat可以 ,但是尽量不要这样使用,可以使用
strncat
来给自己追加。
strcmp
函数介绍
字符串比较函数
int strcmp ( const char * str1, const char * str2 )
第一个字符串大于第二字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
比较规则是按照字典序比较的,如果是大小写的话就按照ASCII码值比较。ASCII码值大,那么字符串中的字符就大。如果一个字符串结束,另一个字符串就和‘ \0 ’,比较,此时就是‘ \0 ’小。
模拟实现
int my_strcmp(const char* str, const char* src)
{assert(str && src);while (*str == *src){if (*str == '\0')return 0;str++;src++;}return *str - *src;
}
strncpy
函数介绍
char * strncpy ( char * destination, const char * source, size_t num )
前两个参数和strcpy是一个意思,第三个参数是要拷贝的数量
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
如果字符串大于num,就拷贝num个,不补‘ \0 ’。
模拟实现
char* my_strncpy(char* str, const char* src, int num)
{char* ret = str;assert(str&& src);while (*str = *src){str++;src++;num--;if (num == 0)break;}while (num){*str = '\0';str++;num--;}return ret;
}
strncat
函数介绍
char * strncat ( char * destination, const char * source, size_t num )
指定在目标字符串后面追加多少个。
追加后补‘ \0 ’。
如果源字符串不够长,有多少个追加多少个。
模拟实现
char* my_strcat(char* str, const char* src, int num)
{char* ret = str;assert(str);assert(src);while (*str != '\0'){str++;}while (*str++ = *src++){num--;if (num == 0){*str = '\0';break;}}return ret;
}
strncmp
函数介绍
int strncmp ( const char * str1, const char * str2, size_t num )
比较前n个字符,返回值与strcmp相同。
模拟实现
int my_strncmp(const char* str, const char* src, int num)
{assert(str && src);while (*str == *src){num--;if (*str == '\0' || num <= 0)return 0;str++;src++;}return *str - *src;
}
strtok
char * strtok ( char * str, const char * delimiters )
sep参数指向一个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
strtok函数找到str中的下一个标记,并将其用‘ \0 ’ 结尾,返回一个指向这个开始位置的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
strtok函数的第一个参数不为NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
strtok函数的第一个参数为NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记则返回NULL
int main()
{char arr[] = "zhangsan@qq.com.cn";char temp = { 0 };temp = strcpy(temp, arr);char* sep = ".@";char* str = NULL;for (str = strtok(arr, temp); str != NULL; str = strtok(NULL, temp)){printf("%s\n", str);}return 0;
}
strstr
函数介绍
const char * strstr ( const char * str1, const char * str2 )
在字符串中找字串,在str1中找str2
返回str2字符串在str1中第一次出现的第一个字符的地址,找不到就返回NULL。
模拟实现
char* my_strstr(const char* str1, const char* str2)
{assert(str1 && str2);const char* cp = str1;const char* s1 = NULL;const char* s2 = NULL;if (*str2 == '\0')//如果字符串是空return str1;while (*cp){s1 = cp;s2 = str2;while (*s1 == *s2 && *s2 && *s1){s1++;s2++;}if (*s2 == '\0')return cp;cp++;}return NULL;
}
strerror
strerror
函数可以把参数部分错误码对应的错误信息的字符串地址返回来。
使用strerror需要包含<string.h>
在C语言库函数中设计一些错误码,当我们库函数在调用的过程中发生了各种错误,要记录下来,这时候记录的就是错误码。
当库函数调用失败的时候会将错误码记录到errno这个变量当中,如过要使用这个变量需要引用<errno.h>这个头文件。
errno是一个C语言的全局变量。
比如我们打开一个文件,不存在那么打开失败,就会把失败的错误码存在errno里面
int main()
{FILE* pf = fopen("add.txt", "r");if (pf == NULL){printf("打开文件失败,原因:%s\n", strerror(errno));return 1;}else{printf("打开文件成功\n");}return 0;
}
perror
perror直接打印错误码所对应的信息,并且会打印参数,然后加一个冒号一个空格。
相当于printf和strerror(errno)的一个组合功能。
int main()
{FILE* pf = fopen("add.txt", "r");if (pf == NULL){perror("fopen");return 1;}else{printf("打开文件成功\n");}return 0;
}