目录
前言
在大家使用C语言进行编程的时候,我们可以发现C中对字符和字符串的处理十分的频繁,但是呢,c它本身是没有字符串类型的,字符串通常放在常量字符串中或者字符数组中。字符串常量只使用于那些对它不做修改的字符串函数,字符数组可适用于任何字符串函数。今天,我们就要对这些函数一探究竟。
求字符串长度
strlen的介绍与使用
size_t strlen ( const char * str )
//strlen的使用 #include <stdio.h> #include <string.h> int main() { char arr[] = "abcdef"; size_t ret = strlen(arr); printf("%zu\n", ret); return 0; }
字符串的'\0'作为结束标志,strlen返回的是'\0'前面出现的字符个数,'\0'不计入其中。
参数指向的字符串必须要以'\0'为结束。
strlen的返回值的类型为size_t,是无符号的。
这里解释一下第三个说明,举个栗子:通过下面代码我们可以发现arr1的长度明显大于arr2的长度,但是结果却是>。这就是因为strlen的返回类型是无符号的,两个无符号的相减,得到的还是无符号的。
int main() { char arr1[] = "xxxxxxx"; char arr2[] = "xxxx"; if (strlen(arr2) - strlen(arr1) > 0) printf(">"); else printf("<"); return 0; }
strlen的模拟实现
方法一 计数器
int my_strlen(char* str) { int count = 0; while (*str != '\0') { count++; str++; } return count; } int main() { char arr[] = "abcdef"; int ret = my_strlen(arr); printf("%d\n", ret); return 0; }
递归二 递归
int my_strlen(char* str) { if (*str == 0) return 0; else return 1 + my_strlen(str + 1); } int main() { char arr[] = "abcdef"; int ret = my_strlen(arr); printf("%d\n", ret); return 0; }
方法三 指针 - 指针
int my_strlen(char* str) { char* p = str; while (*str != '\0') { str++; } return str - p; } int main() { char arr[] = "abcdef"; int ret = my_strlen(arr); printf("%d\n", ret); return 0; }
长度不受限制的字符串函数
strcpy的介绍和使用
char * strcpy ( char * destination, const char * source )
//使用strcpy函数 int main() { char arr1[] = "abcdef"; char arr2[] = "XXX"; strcpy(arr1, arr2); printf("%s\n", arr1); return 0; }
源字符串必须以'\0'结束
会将字符串中的'\0'拷贝到目标空间
目标空间必须可变
这里解释一下第三个说明:strcpy的第一个参数只能是可变参数,也就是字符数组。不能是常量字符串,因为它不能改变。
strcpy的模拟实现
//模拟实现strcpy函数 //优化前 char* my_strcpy(char* dest, char* source) { char* ret = dest; while (*source != '\0') { *dest = *source; dest++; source++; } *dest = '\0'; return ret; } //优化后 char* my_strcpy(char* dest, const char* source) { char* ret = dest; assert(dest && source); while (*dest++ = *source++); return ret; } int main() { char arr1[] = "abcdef"; char arr2[] = "XXX"; my_strcpy(arr1, arr2); printf("%s\n", arr1); return 0; }
strcat的介绍和使用
char * strcat ( char * destination, const char * source )
//使用strcat函数 int main() { char arr1[20] = "abcdef"; char arr2[] = "xxxxx"; strcat(arr1, arr2); printf("%s\n", arr1); return 0; }
源字符串必须以'\0'结束
目标空间必须有足够的大,可以容纳下源字符串的内容
目标空间必须可以修改
这里解释一下第二个说明:因为要将源字符串放到目标字符串后面,所以他的空间大小必须大于等于两个字符串的大小,不然会溢出。
strcat的模拟实现
//模拟实现strcat char* my_strcat(char* str1, const char* str2) { assert(str1 && str2); char* ret = str1; while (*str1) { str1++; } while (*str1++ = *str2++); return ret; } int main() { char arr1[20] = "abcdef"; char arr2[] = "XXXX"; my_strcat(arr1, arr2); printf("%s\n", arr1); return 0; }
strcmp的介绍和使用
int strcmp ( const char * str1, const char * str2 );
//使用strcmp函数 int main() { char arr1[] = "adcdef"; char arr2[] = "adsdf"; int ret =strcmp(arr1, arr2); printf("%d\n", ret); return 0; }
第一个字符串大于第二个字符串,返回大于0的数字
第一个字符串等于第二个字符串,返回0
第一个字符串小于第二个字符串,返回小于0的数字
它们比较的是对应字符的ASCII码值,要是相等就比较下一个
strcmp的模拟实现
//模拟实现strcmp函数 int my_strcmp(const char* str1, const char* str2) { assert(str1 && str2); while (*str1 == *str2) { if (*str1 == '\0') return 0; else { str1++; str2++; } } if (*str1 > *str2) return 1; else if (*str1 < *str2) return -1; } int main() { char arr1[] = "adcdef"; char arr2[] = "abcdef"; int ret = my_strcmp(arr1, arr2); printf("%d\n", ret); return 0; }
长度受限制的字符串函数
strncpy的介绍和使用
char * strncpy ( char * destination, const char * source, size_t num )
//使用strncpy函数 int main() { char arr1[] = "adcdefdsaf"; char arr2[] = "XXXxx"; strncpy(arr1, arr2, 3); printf("%s\n", arr1); return 0; }
拷贝num个字符从源字符串到目标字符串
如果源字符串的长度小于num,拷贝完源字符串后,在目标后面追加0,直到num个。
strncpy的模拟实现
//模拟strncpy char* my_strncpy(char* dest, const char* str, int num) { assert(dest && str); char* ret = dest; int i = 0; for (i = 1; i <= num; i++) { if (strlen(ret) < i) { *dest = '\0'; } *dest = *str; dest++; str++; } return ret; } int main() { char arr1[] = "adcdefdsaf"; char arr2[] = "XXXxx"; my_strncpy(arr1, arr2, 8); printf("%s\n", arr1); return 0; }
strncat的介绍和使用
char * strncat ( char * destination, const char * source, size_t num )
//使用strncat函数 int main() { char arr1[20] = "adcdefdsaf"; char arr2[] = "XXXxxxx"; strncat(arr1, arr2, 5); printf("%s\n", arr1); return 0; }
将源字符串 的第一个数字字符追加到目标,外加一个终止空字符。
如果源字符串中 C 字符串的长度小于 num,则仅复制终止空字符之前的内容。
strncat的模拟实现
//模拟strncat函数 char* my_strncat(char* dest, const char* str, int num) { char* ret = dest; assert(dest && str); while (*dest != '\0') { dest++; } int count = 0; int count = 0; while (count++, count<=num && count<=strlen(str)) { *dest = *str; dest++; str++; } *dest = '\0'; return ret; } int main() { char arr1[20] = "adcdefd"; char arr2[] = "XXXxxxx"; my_strncat(arr1, arr2, 19); printf("%s\n", arr1); return 0; }
strncmp的介绍和使用
int strncmp ( const char * str1, const char * str2, size_t num )
//使用strncmp函数 int main() { char arr1[] = "abcdefg"; char arr2[] = "abces"; int ret = strncmp(arr1, arr2, 4); printf("%d\n", ret); return 0; }
比较出现字符不一样或者一个字符串结束或者num个字符全部比较完
strncmp的模拟实现
//模拟strncmp函数 int my_strncmp(char* str1, char* str2, int num) { int i = 0; for (i = 1; i <= num; i++) { if (*str1 == *str2) { if (*str1 == '\0') return 0; str1++; str2++; } else if (*str1 > *str2) return 1; else if (*str1 < *str2) return -1; } } int main() { char arr1[] = "aefg"; char arr2[] = "abces"; int ret = my_strncmp(arr1, arr2, 4); printf("%d\n", ret); return 0; }
字符串查找函数
strstr的介绍和使用
char * strstr ( const char * str1, const char * str2 )
//使用strstr函数 int main() { char arr1[] = "abbbcd"; char arr2[] = "bbc"; char* p = strstr(arr1, arr2); puts(p); return 0; }
作用是返回指向 str2 中第一次出现的 str1 的指针,如果 str2 不是str1 的一部分,则返回一个空指针。匹配过程不包括终止空字符,但它到此为止。
返回值是指向 str1 中指定的整个字符序列在 str2 中首次出现的指针,如果序列在 str1 中不存在,则为 null 指针。
strstr的模拟实现
//模拟实现strstr函数 char* my_strstr(char* dest, const char* source) { assert(dest && source); char* cp = dest; char* s1 = dest; char* s2 = source; if (*source == '\0') return dest; while (*cp != '\0') { while (*s1 == *s2&& *s1 && *s2) { s1++; s2++; } if (*s2 == '\0') return cp; else { cp++; s1 = cp; s2 = source; } } return NULL; } int main() { char arr1[] = "abbbbcd"; char arr2[] = "bbc"; my_strstr(arr1, arr2); printf("%s\n", my_strstr(arr1, arr2)); return 0; }
strtok的介绍
char * strtok ( char * str, const char * delimiters )
delimiters参数是一个字符串,定义了用做分隔符的集合
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分割符
strtok函数找到str中的下一个标记,并将其用'\0'结尾,返回一个指向这个标记的指针 (注: strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容 并且可修改。)
strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标 记。
如果字符串中不存在更多的标记,则返回 NULL 指针。
strtok的使用
//使用strtok函数 int main() { char arr[] = "3435151626@qq.com"; char cpy[20]; strcpy(cpy, arr); char* ret = NULL; char sep[] = "@."; for (ret = strtok(cpy, sep); ret != NULL; ret = strtok(NULL, sep)) { printf("%s\n", ret); } return 0; }
错误信息报告
strerror的介绍和使用
char * strerror ( int errnum );
//使用strerror函数 int main() { int i = 0; for (i = 0; i < 9; i++) { printf("%d: %s\n", i, strerror(i)); } return 0; }
对应的错误信息
字符分类函数
字符转换函数
int tolower ( int c ); int toupper ( int c );
tolower将大写转小写
toupper将小写转大写
转换函数的使用
int main() { char ch[10] = { 0 }; gets(ch); char* p = ch; while (*p) { if (isupper(*p)) { *p = tolower(*p); } p++; } printf("%s\n", ch); return 0; }