注:点击蓝色的标题可以跳转到官方网站查阅更权威的函数解释哦。
字符串函数
需要包含头文件<string.h>
strlen
size_t strlen ( const char * str );
- 字符串以
\0
作为结束标志,strlen()
函数返回的是在字符串中\0
前面出现的字符个数(不包含\0
) - 参数指向的字符串必须要以
\0
结束 - 注意函数的返回值为
size_t
,是无符号的(注意无符号和有符号数的大小比较,如果有还不清楚的小伙伴请看这里👉C语言陷阱——无符号数和有符号数的大小比较)
具体使用:
#include<stdio.h> #include<string.h> int main() { char str[] = "abcdefg"; int len = strlen(str); pritnf("%d\n", len); return 0; }
模拟实现:
#include<stdio.h> size_t my_strlen(const char* str) { size_t count = 0; while (*str) { count++; str++; } return count; } int main() { char str[] = "abcdef"; int len = my_strlen(str); printf("len = %d\n", len); return 0; }
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).——将
source
指向的 C 字符串复制到destination
指向的数组中,包括终止的 null 字符(并在该点停止)。 - 源字符串必须以
\0
结束 - 会将源字符串中的
\0
拷贝到目标空间destination
- 目标空间必须足够大,以确保能存放源字符串
- 目标空间必须可变
具体使用:
#include<stdio.h> #include<string.h> int main() { char str1[20] = "xxxxxxxxxxxxxxxxxx" ; char str2[20] = "abcde"; printf("%s", strcpy(str1, str2)); return 0; }
模拟实现:
#include<stdio.h> #include<string.h> char* my_strcpy(char* destination, const char* source) { char* head = destination; while (*source) { *destination++ = *source++; } *destination = '\0'; return head; } int main() { char str1[20] = "xxxxxxxxxxxxxxxxxx" ; char str2[20] = "abcde"; printf("%s", my_strcpy(str1, str2)); return 0; }
strcmp
int strcmp ( const char * str1, const char * str2 );
- This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs until the characters differ or until a terminating null-character is reached.——此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续以下对,直到字符不同或达到终止空字符。
- 标准规定:
- 第一个字符串大于第二个字符串,则返回大于0的数字
- 第一个字符串等于第二个字符串,则返回0
- 第一个字符串小于第二个字符串,则返回小于0的数字
具体使用:
#include<stdio.h> #include<string.h> int main() { char str1[20] = "bbcdexxxxxx" ; char str2[20] = "abcde"; printf("%d\n", strcmp(str1, str2)); return 0; }
模拟实现:
#include<stdio.h> int my_strcmp(const char* str1, const char* str2) { while (*str1 == *str2) { if (*str1 == '\0') return 0; str1++; str2++; } if (*str1 > *str2) return 1; else return -1; } int main() { char str1[20] = "bcdexxxxxx" ; char str2[20] = "abcde"; printf("%d\n", my_strcmp(str1, str2)); return 0; }
strcat
char * strcat ( char * destination, const char * source );
- Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null-character is included at the end of the new string formed by the concatenation of both in destination.——将源字符串的副本追加到目标字符串。目标中的终止空字符被源的第一个字符覆盖,并且在目标中由两者串联形成的新字符串的末尾包含一个空字符。
- 源字符必须以‘\0’结束
- 目标空间必须足够大,能够容纳下源字符串的内容
- 目标空间必须可修改
具体使用:
#include<stdio.h> #include<string.h> int main() { char str1[20] = "abcde" ; char str2[20] = "abcde"; printf("%s\n", strcat(str1, str2)); return 0; }
模拟实现:
#include<stdio.h> char* my_strcat(char* destination, const char* source) { char* head = destination; while (*destination) destination++; while (*source) { *destination++ = *source++; } *destination = '\0'; return head; } int main() { char str1[20] = "abcde" ; char str2[20] = "abcde"; printf("%s\n", my_strcat(str1, str2)); return 0; }
前面我们提到的字符串函数strcpy(), strcmp(), strcat()
,可以说只有遇到结束符\0
函数才会停止,跟传入的字符串长度没有关系,我们将这一类字符串函数称为长度不受限制的字符串函数。与之对应的,我们也有三个与之对应的长度受限制的字符串函数strncpy(), strncmp(), ctrncat()
strncpy
char * strncpy ( char * destination, const char * source, size_t num );
- Copies the first num characters of source to destination. If the end of the source C string (which is signaled by a null-character) is found before num characters have been copied, destination is padded with zeros until a total of num characters have been written to it.——将源的第一个字符数复制到目标。如果在复制 num 个字符之前找到源 C 字符串的末尾(由 null 字符表示),则目标将填充零,直到总共写入 num 个字符为止。
- 拷贝num个字符从源字符串到目标空间
- 如果原字符串的长度小于num,则拷贝完源字符串后,在目标的后面追加0,直到num个
具体使用:
#include<stdio.h> #include<string.h> nt main() { char str1[20] = "xxxxxxxxxxxxxxxxxxxx" ; char str2[20] = "abcde"; printf("%s\n", strncpy(str1, str2, 20)); return 0; }
模拟实现:
#include<stdio.h> char* my_strncpy(char* destination, const char* source, size_t num) { char* head = destination; while (num && *source) { num--; *destination++ = *source++; } while (num--) *destination++ = '\0'; return head; } int main() { char str1[20] = "x" ; char str2[20] = "abcde"; printf("%s\n", my_strncpy(str1, str2, 4)); return 0; }
strncmp
int strncmp ( const char * str1, const char * str2, size_t num );
- Compares up to num characters of the C string str1 to those of the C string str2.
This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs until the characters differ, until a terminating null-character is reached, or until num characters match in both strings, whichever happens first.——将 C 字符串 str1 的字符数与 C 字符串 str2 的字符数进行比较。此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续使用以下对,直到字符不同或直到达到终止的空字符亦或者直到两个字符串中的 num 字符匹配,以先发生者为准。 - 标准规定:
- 第一个字符串大于第二个字符串,则返回大于0的数字
- 第一个字符串等于第二个字符串,则返回0
- 第一个字符串小于第二个字符串,则返回小于0的数字
具体使用:
#include<stdio.h> #include<string.h> int main() { char str1[20] = "abcdf" ; char str2[20] = "abcde"; int ret = (str1, str2, 5); if (ret == 0) printf("Equal: %d\n",ret); else printf("No Equal: %d\n", ret); return 0; }
模拟实现:
#include<stdio.h> int my_strncmp(const char* str1, const char* str2, size_t num) { while (num && *str1 == *str2) { if (*str1 == '\0') return 0; str1++; str2++; num--; if (num == 0) return 0; } if (*str1 > *str2) return 1; else return -1; } int main() { char str1[20] = "abcdf" ; char str2[20] = "abcde"; int ret = my_strncmp(str1, str2, 5); if (ret == 0) printf("Equal: %d\n",ret); else printf("No Equal: %d\n", ret); return 0; }
strncat
char * strncat ( char * destination, const char * source, size_t num );
- Appends the first num characters of source to destination, plus a terminating null-character.If the length of the C string in source is less than num, only the content up to the terminating null-character is copied.——将源的第一个数字字符追加到目标,外加一个终止空字符。如果源中 C 字符串的长度小于 num,则仅复制终止空字符之前的内容。
具体使用:
#include<stdio.h> #include<string.h> int main() { char str1[20] = "x" ; char str2[20] = "abcde"; printf("%s\n", strncat(str1, str2, 10)); return 0; }
模拟实现:
#include<stdio.h> char* my_strncat(char* destination, const char* source, size_t num) { char* head = destination; while (*destination) destination++; while (num && *source) { num--; *destination++ = *source++; } return head; } int main() { char str1[20] = "x" ; char str2[20] = "abcde"; printf("%s\n", my_strncat(str1, str2, 5)); return 0; }
strstr
char * strstr ( const char * str1, const char * str2 );
- Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.——返回指向 str1 中第一次出现的 str2 的指针,如果 str2 不是 str1 的一部分,则返回一个空指针。
- 即找到子串str2在主串中第一次出现的位置,并返回指向这个位置的指针,如果如果 str2 不是 str1 的一部分,则返回一个空指针。
具体使用:
#include<stdio.h> #include<string.h> int main() { char str1[20] = "abcdfababcde" ; char str2[20] = "abcde"; printf("%s\n", strstr(str1, str2)); return 0; }
模拟实现:
注:关于strstr的模拟实现博主专门写了一篇博文来进行详细的说明,大家感兴趣可以看看模拟实现strstr详解
暴力实现:
#include<stdio.h> #include<string.h> char* my_strstr(const char* str1, const char* str2) { int len1 = strlen(str1); int len2 = strlen(str2); if (len2 > len1) return NULL; while (*str1) { if (*str1 != *str2) str1++; else { char* temp1 = str1; char* temp2 = str2; while (*temp2 && *temp1 == *temp2) { temp1++; temp2++; } if (*temp2 == '\0') return str1; else str1++; } } return NULL; } int main() { char str1[20] = "abcdfababcde" ; char str2[20] = "abcde"; printf("%s\n", my_strstr(str1, str2)); return 0; }
KMP实现
#include<stdio.h> #include<stdlib.h> #include<string.h> void GetNext(int* next, char* str) { int len = strlen(str); next[0] = -1; int k = -1; int begin = 1; while (begin < len) { if (k == -1 || str[begin - 1] == str[k]) { next[begin] = k + 1; k++; begin++; } else { k = next[k]; } } } char* my_strstr(const char* str1, const char* str2) { int len1 = strlen(str1); int len2 = strlen(str2); if (len2 > len1) return NULL; int* next = (int*)malloc(sizeof(int) * len2); GetNext(next, str2); int begin1 = 0; int begin2 = 0; while (begin1 < len1 && begin2 < len2) { if (str1[begin1] == str2[begin2]) { begin1++; begin2++; } else { if (begin2 == 0) begin1++; else begin2 = next[begin2]; } } if (begin2 == len2) return &str1[begin1 - begin2]; else return NULL; } int main() { char str1[20] = "abcdfababcde" ; char str2[20] = "abcde"; printf("%s\n", my_strstr(str1, str2)); return 0; }
strtok
char * strtok ( char * str, const char * delimiters);
- delimiters参数是一个字符串,定义了用作分隔符的字符集合
- 第一个参数指定一个字符串,它包含了0个或多个由delimiters字符串中一个或者多个分隔符分割的标记
- strtok函数找到str中的下一个标记,并将其用‘\0’结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改)
- strtok函数的第一个参数不为NULL,函数将找到str中的第一个标记,strtok函数将保存它在字符串中的位置
- strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记
- 如果字符串中不存在更多的标记,则返回NULL指针
具体使用:
#include<stdio.h> #include<string.h> void Text1() { char str[] = "hhh333@qq.com"; char seq[] = "@."; char _str[100] = { 0 }; strcpy(_str, str); printf("%s\n", strtok(_str, seq)); printf("%s\n", strtok(NULL, seq)); printf("%s\n", strtok(NULL, seq)); } void Text2() { char str[] = "hhh333@qq.com"; char seq[] = "@."; char _str[100] = { 0 }; strcpy(_str, str); char* temp = strtok(_str, seq); for (; temp != NULL; temp = strtok(NULL, seq)) { printf("%s\n", temp); } } int main() { Text1(); Text2(); return 0; }
模拟实现:
char* my_strtok(char* str, const char* delimiters) { static char* temp = NULL; if (str != NULL) { char* head1 = str; while (*head1) { char* head2 = delimiters; while (*head2) { if (*head1 != *head2) head2++; else { *head1 = '\0'; temp = head1 + 1; return str; } } head1++; } return str; } else { if (temp == NULL) return NULL; char* head1 = temp; char* cur = temp; while (*head1) { char* head2 = delimiters; while (*head2) { if (*head1 != *head2) head2++; else { *head1 = '\0'; temp = head1 + 1; return cur; } } head1++; } temp = NULL; return cur; } } void Text2() { char str[] = "hhh333@qq.com"; char seq[] = "@."; char _str[100] = { 0 }; strcpy(_str, str); char* temp = my_strtok(_str, seq); for (; temp != NULL; temp = my_strtok(NULL, seq)) { printf("%s\n", temp); } } int main() { Text2(); return 0; }
strerror
char * strerror ( int errnum );
- 返回错误码所对应的错误信息
- 这里有必要进行说明:
- 库函数在执行的时候,如果发生了错误,会将一个错误码存放在
errno
这个自带的全局变量中
- 我们可以来看看数字1~9所对应的错误信息(0表示正常):
#include<stdio.h> #include<string.h> #include<errno.h> int main() { for (int i = 1; i < 9; i++) printf("%s\n", strerror(i)); return 0; }
output:
/* Operation not permitted No such file or directory No such process Interrupted function call Input/output error No such device or address Arg list too long Exec format error */
具体使用:
#include<stdio.h> #include<string.h> #include<errno.h> int main() { FILE* fp = fopen("unexist.txt", "r"); if (fp == NULL) { printf("Error opening unexist.txt: %s\n", strerror(errno)); //errno: Last error number } fclose(fp); return 0; }
字符分类函数
函数 | 如果它的参数符合下列条件就返回真 |
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 | 任何可打印字符,包括图形字符和空白字符 |
注:ASCII为0~31的字符均为不可打印字符