博客制作不易,欢迎各位点赞👍+收藏⭐+关注
目录
前言
在C语言中,由于字符串的操作较频繁,所以C语言本身提供了一些对于字符串处理的库函数。
函数 | 作用 |
strlen | 求字符串长度(不包含'\0') |
strcpy |
复制字符串 |
strcat | 横向连接字符串 |
strcmp | 比较两个字符串的大小,返回比较值 |
strncpy | 根据提供的字节大小复制字符串大小 |
strncat | 字符串末尾连接n个字符 |
strncmp | 比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完 |
strstr | 搜索一个字符串在另一个字符串中的第一次出现。找到所搜索的字符串,则该函数返回第一次匹配的字符串的地址; 如果未找到所搜索的字符串,则返回NULL |
strtok | 通过提供的分隔符字符串,将字符串分割成一个个片段 |
strerror | 将错误码给转化成错误信息 |
memcpy | 内存拷贝 |
memmove | 拷贝一定长度的内存的内容 |
memset | 在一段内存块中填充某个给定的值 |
memcmp | 比较两个内存块 |
一、字符串函数
1. strlen
size_t strlen (const char* str);
注意:
1)字符串已经将 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' );
2)参数的字符串必须要以'\0'结束,不能没有'\0';
3)注意函数的返回值是 size_t ,是无符号类型。
模拟实现函数:
#include<assert.h> size_t my_strlen(const char* ch) { assert(ch); size_t count = 0; while (*ch++) { count++; } return count; }
2.strcpy
char* strcpy (char* destination, const char* source);
注意:
1)源字符串必须以 '\0' 结束;
2)该函数会将源字符串中的'\0'一同拷贝到目标空间,如果目标字符串原先就有内容,就会被拷贝的内容覆盖掉,包括'\0'也是;
3)目标空间必须足够大,以确保能存放源字符串,如果放不下就会造成数组越界访问,为非法访问空间;
4)目标空间必须可变,不能是常量字符串。
模拟实现函数:
#include<assert.h> char* my_strcpy(char* dest, const char* src) { char* p = dest; assert(src && dest); while(*dest++ = *src++) ; return p; }
3. strcat
char* strcat (char* destination, const char* source);
注意:
1)源字符串必须以 '\0' 结束;
2)目标空间必须有足够的大,能容纳下源字符串的内容;
3)目标空间必须可修改。
模拟实现函数:
#include<assert.h> #include<string.h> char *my_strcat(char *str1, const char *str2) { char *start = str1; assert(str1 && str2); str1 += strlen(str1); while( *str1++ = *str2++ ) ; return start; }
4. strcmp
int strcmp ( const char * str1, const char * str2 );
注意:
1)第一个字符串大于第二个字符串,则返回大于0的数字;
2)第一个字符串等于第二个字符串,则返回0;
3)第一个字符串小于第二个字符串,则返回小于0的数字。
ps:在 VS 环境中,第一种情况返回的是 1 ,第二种情况同样返回 0 ,第三种情况返回 -1 。
模拟实现函数:
#include<assert.h> int my_strcmp(const char *str1, const char *str2) { assert(str1 && str2); while(*str1 == *str2) { if(*str1 == '\0') return 0; str1++; str2++; } return *str1 - *str2; }
5.strncpy
char* strncpy (char* destination, const char* source, size_t num);
注意:
1)如果源字符串的长度小于 num ,则拷贝完源字符串之后,在目标的后边追加 '\0' ,直到 num 个;
2)拷贝 num 个字符就只会拷贝 num 个字符,不会再往后补上一个'\0'。
6. strncat
char* strcat (char* destination, const char* source, size_t num);
注意:
同样地,这个函数与 strcat 在使用上也只有新增一个参数来确认需要追加字符串中的多少个字符的区别而已,这个函数使用起来就比 strncpy 省心多了,因为这个函数会在追加之后再追加一个 '\0'。
7. strncmp
char* strncmp (const char* str1, const char* str2, size_t num);
这个函数使用方法与 strcmp 相比也只有最后一个参数的区别,不多加说明。
8.strstr
char* strstr (const char* str1, const char* str2);
这是一个可以判断一个字符串是否是另一个字符串的子串的函数。如果 str2 是 str1 的子串,即返回 str2 在 str1 中首次出现的位置的地址;如果不是则返回NULL。
模拟实现函数:
#include<assert.h> char* my_strstr(const char* str1, const char* str2) { assert(str1 && str2); const char *p1 = str1; const char *p2 = str2; const char *start1 = p1; const char *start2 = p2; if(*str2 == '\0') return (char*)str1; while( *p1 ) { while(*p1 == *p2 && *p1 != '\0') { p1++; p2++; } if(*p2 == '\0') return (char*)start1; start1++; p1 = start1; p2 = start2; } return NULL; }
9.strtok
char* strtok (char* str, const char* sep);
strtok,是一个可以按照给出的分隔符字符串,将字符串分割,我们进行第一次传参的时候,把字符串传过去,然后开始找分隔符,找到分隔符用'\0'代替,当要进行第二次分割的的时候,传参传NULL即可,当传参传NULL的时候,strtok函数会找到上一次标记的地址,然后向后进行切割,如果在我们的字符串中,没有我们的分隔符,就会返回NULL。
二、错误信息报告
1.strerror
char * strerror ( int errnum );
strerror是一个可以将错误码转换成错误信息的函数,其中我们的错误码会保存在一个叫做errno的函数中,它需要引头文件<errno.h>。
三、字符函数
函数 | 如果他的参数符合下列条件就返回真 |
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 | 任何可打印字符,包括图形字符和空白字符 |
字符转换
大写 -> 小写 | tolower | int tolower (int c); |
小写 -> 大写 | toupper | int toupper (int c); |
四、内存操作函数
1. memcpy
void* memcpy (void* destination, const void* source, size_t num);
注意:
1)函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置;
2)这个函数在遇到 '\0' 的时候并不会停下来;
3)如果source和destination有任何的重叠,复制的结果都是未定义的。
模拟实现函数:
#include<assert.h> void *my_memcpy(void *str1, const void *str2, size_t byte) { assert(str1 && str2); size_t i = 0; while( i < byte ) { *((char *)str1 + i) = *((char *)str2 + i); i++; } return str1; }
2. memmove
void* memmove (void* destination, const void* source, size_t num);
注意:
1)和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的;
2)如果源空间和目标空间出现重叠,就得使用memmove函数处理。
模拟实现函数:
#include<assert.h> void *my_memmove(void *str1, const void *str2, size_t byte) { assert(str1 && str2); size_t i = 0; if(str1 < str2) { while( i < byte ) { *((char *)str1 + i) = *((char *)str2 + i); i++; } } else { while( i < byte ) { *((char *)str1 + byte - i - 1) = *((char *)str2 + byte - i - 1); i++; } } return str1; }
3. memcmp
int memcmp (const void* ptr1, const void* ptr2, size_t num);
注意:
1)比较从ptr1和ptr2指针开始的num个字节;
2)返回值由比较的两个字节内容大小决定。
模拟实现函数:
#include<assert.h> int my_memcmp(const void *str1, const void *str2, size_t byte) { assert(str1 && str2); size_t i = 0; for(i = 0; i < byte; i++) { if( *((char *)str1 + i) != *((char *)str2 + i) ) return *((char *)str1 + i) - *((char *)str2 + i); } return 0; }
总结
上述函数都是我们常会在代码中使用到的,熟练掌握起来为我们提供很大的帮助。当然,除此之外,C语言的库函数中还有许多有趣的有关字符和字符串的函数,如果你有兴趣想要了解,可以通过cplusplus网站或cppreference网站找到它们,里面都有对每一个函数详细的各个部分的说明、作用的解析和示例,博主就不一一赘述了。