一.函数介绍
1.1 strlen
size_t strlen(const char *str);
1.字符串以‘\0’作为结束标志,strlen函数返回的是在字符串中‘\0’前面出现的字符个数(不包括‘\0’)
2.函数指向的字符串必须要一‘\0’结束。
3.注意函数的返回值为size_t,是无符号的(易错)
eg:
strlen 的模拟实现
#include<stdio.h> #include<assert.h> size_t my_strlen(const char* arr) { assert(arr);//确保为非指针 char* start = arr; char* end = arr; while (*end != '\0') { end++; } return end - start; } int main() { char arr[] = "abcdefg"; int ret=my_strlen(arr); printf("%d", ret); return 0; }
1.2 strcpy
char* strcpy(char* destination,const char* source);
1. 源字符串必须以‘\0’结束。
2.会将源字符串中的‘\0’拷贝到目标空间
3.目标空间必须足够大,以确保能存放源字符串
4.目标空间必须可变
strcpy 的模拟实现
#include<stdio.h> #include<assert.h> char* my_strcpy(char* dest, const char* src) { assert(dest); assert(src); char* ret = dest; while (*dest++ = *src++) { ; } return ret; } int main() { char arr1[20] = "abc"; char arr2[] = "hello world!"; printf("%s\n", my_strcpy(arr1, arr2)); return 0; }
1.3 stract
char * stract( char * destination,const char * source);
1.源字符串与目标字符串必须以‘\0’结束
2.目标空间必须有足够大,能容纳下源字符串的内容
3.目标空间必须可修改
4.字符串不能够自己给自己追加
使用和模拟:
char* my_strcat(char* dest, const char*src) { //1.找目标空间中的\0 char* cur = dest; while (*cur) { cur++; } //2.拷贝源头数据到\0之后的空间 while (*cur++ = *src++) { ; } return dest; } int main() { char arr1[20] = "hello"; char arr2[] = " world!"; //my_strcat(arr1,arr2); printf("%s\n", strcat(arr1,arr2)); return 0; }
1.4 strcmp
int * strcmp ( const char * str1,const char * str2);(比较的为字符串中每个字符的ASCII)
1. 第一个字符串大于第二个字符串,则返回大于0的数字
2. 第一个字符串等于第二个字符串,则返回0
3.第一个字符串小于第二个字符串,则返回小与0的数字
模拟实现:
int my_strcmp(const char* s1, const char* s2) { assert(s1 && s2); while (*s1 == *s2) { if (*s1 == '\0') { return 0; } s1++; s2++; } return *s1 - *s2; }
1.5 strncpy
char * strncpy( char * destination , const char * source ,size_t num);
1. 拷贝num个字符串到目标空间
2.如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
int main() { char arr1[20] = "abcdefghi"; char arr2[] = "xxxx"; strncpy(arr1, arr2, 8); printf("%s\n", arr1); return 0; }
1.6 strncat
chat * strncat (char * destination , const char * source, size_t num);(可以给自己追加)
int main() { char arr1[20] = "abcdef\0qqqqqq"; char arr2[] = "xyz"; strncat(arr1, arr2, 2); printf("%s\n", arr1); return 0; }
1.7 strncmp
int strncmp (cnst char * str1, cnst char *str 2,size_t num);
1. int main() { int ret = strncmp("abcdef", "abc", 4); printf("%d\n", ret); return 0; }
1.8 strstr
char * strstr ( const char *str1, const char * str2);
在一个字符串中另外一个字符串是否存在,存在:返回子串第一次出现的位置;不存在,返回NULL。
int main() { char arr1[] = "abcdefabcdef"; char arr2[] = "cdef"; char *p= strstr(arr1, arr2); if (p == NULL) { printf("不存在\n"); } else { printf("%s", p); } return 0; }
模拟实现:
char* my_strstr(const char* str1, const char* str2) { const char* s1 = str1; const char* s2 = str2; const char* p = str1; if (*str2 == '\0') { return str1; } while (*p) { s1 = p; s2 = str2; while (*s1 != '\0' && *s2 != '\0' && (*s1 == *s2)) { s1++; s2++; } if (*s2 == '\0') { return (char*)p;//找到了 } p++; } return NULL;//找不到子串 } //KMP 算法 - B站搜索:比特大博哥 //难度也比较大一些 int main() { char arr1[] = "abcdefabcdef"; char arr2[] = "cde"; char* p = my_strstr(arr1, arr2); if (p == NULL) { printf("不存在\n"); } else { printf("%s\n", p); } return 0; }
1.9 strtok
char * strok( char * str,const char * sep);
1.sep 参数是个字符串,定义了用作分隔符的字符集合
2.第一个参数指定一个字符串,它包含了0个或者多个sep字符串中一个或者多个分隔符分割的标记。
3.strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容 并且可修改。)
4.strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串 中的位置。
5.strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标 记。
6.如果字符串中不存在更多的标记,则返回 NULL 指针。
int main() { char arr[] = "akai@bitedu.com"; char buf[200] = { 0 };//"akai@bitedu.com" strcpy(buf, arr); const char* p = "@."; char* str = NULL; for (str=strtok(buf, p); str!=NULL; str=strtok(NULL, p)) { printf("%s\n", str); } return 0; }
1.10 strerror
char * strerror (int errnum)
返回错误码所对应的错误信息
使用:
//错误码记录到错误码的变量中 //errno - C语言提供的全局的错误变量 //#include <errno.h> int main() { FILE* pf = fopen("test.txt", "r"); if (pf == NULL) { perror("可自定义");//打印的依然是errno变量中错误码对应的错误信息 //printf("%s\n", strerror(errno)); //printf("%s\n",errno) return 1; } //读文件 fclose(pf); pf = NULL; return 0; }
1.11 memcpy、memmove
void * memcpy ( void * destination,const void * source , size_t num)
memcpy:
1. 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
2.这个函数在遇到 '\0' 的时候并不会停下来。
3. 如果source和destination有任何的重叠,复制的结果都是未定义的
memmove:
和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。 如果源空间和目标空间出现重叠,就得使用memmove函数处理。
#include <stdio.h> #include <ctype.h> void* my_memcpy(void* dest, void* src, size_t num) { void* ret = dest; assert(dest); assert(src); while(num--) { *(char*)dest = *(char*)src; dest = (char*)dest + 1; src = (char*)src + 1; } return ret; } void* my_memmove(void* dest, void* src, size_t num) { void* ret = dest; assert(dest); assert(src); if (dest < src)//1 前->后 { while(num--) { *(char*)dest = *(char*)src; dest = (char*)dest + 1; src = (char*)src + 1; } } else //2 3 后->前 { while (num--) { *((char*)dest + num) = *((char*)src + num); } } return ret; } //memcpy只需要实现不重叠的拷贝就可以了 //memmove是需要实现重叠内存的拷贝的 int main() { int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; memcpy(arr1 + 2, arr1, 20);//无法实现重叠字符串 memmove(arr1+2, arr1, 20); int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; int arr2[10] = { 0 }; my_memcpy(arr2, arr1, 20); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", arr2[i]); } return 0; }
1、12 memcomp
int memcmp ( const void * ptr1, const void * ptr2, size_t num )
比较从ptr1和ptr2指针开始的num个字节
和strncmp类似,但接受的类型更广。
1、13 memset
void * memset (void * ptr , int value , size_t num)
将 ptr 所指向的内存块的前 num 个字节设置为指定的值(解释为无符号字符)
#include <stdio.h> #include <string.h> int main () { char str[] = "almost every programmer should know memset!"; memset (str,'-',6); puts (str); return 0; }
二、字符分类函数
2.1 iscntrl
int iscntrl ( int c )
检查字符 c 是否为控制字符
#include <stdio.h> #include <ctype.h> int main () { int i=0; char str[]="first line \n second line \n"; while (!iscntrl(str[i])) { putchar (str[i]); i++; } return 0; } //此代码逐个字符打印字符串,直到遇到破坏 while 循环的控制字符。在这种情况下,将仅打印第一行,因为 //该行以“\n”结尾,这是一个控制字符(ASCII 代码0x0a)。
2.2 isspace
int isspace(int c)
检查c是否为空白字符:空白字符:空格‘ ’,换页‘\f’,换行'\n',回车‘\r’,制表符'\t'或者垂直制表符'\v'。若是空白字符,则为真,返回大于0的数;否则为假,返回值为0;
#include <stdio.h> #include <ctype.h> int main() { char c; int i = 0; char str[] = "Example sentence to test isspace\n"; while (str[i]) { c = str[i]; if (isspace(c))//判断是否为空白字符 c = '\n';//若是空白字符,将空白字符替换为'\n' putchar(c); i++; } return 0; }
2.3 isdigit、isxdigit、 islower 、isupper、isalpha、isalnum、ispunct、isgraph、isprint、tolower、toupper
int ——(int c)
isdigit:检查是否为数字字符(十进制数0~9)
isxdigit:检查是否为十六进制数字字符
十六进制是以下任意数字:1、2、3、4、5、6、7、8、9、a、b、c、d、e、f、A、B、C、D、E、F
islower:判断 c 是否为小写字母:a~z
isupper:判断 c 是否为大写字母:A~Z
isalpha:判断 c 是否为字母:a~z A~Z
isalnum:判断 c 是否为十进制数字或者为大、小写字母
ispunct:判断 c 是否为标点符号字符,任何不属于数字或者字母的图形字符(可打印)
isgraph:检查 c 是否为具有图形表示形式的字符,具有图形表示形式的字符是除空格字符(' ')之外可以打印的字符(由isprint确定)。
isprint:检查 c 是否为可打印字符,对于标准 ASCII 字符集(由“C”区域设置使用),打印字符的所有 ASCII 代码都大于 0x1f(美国),但 0x7f (DEL) 除外。
对于与 isprint 相同的情况,isgraph 返回 true,但空格字符 (' ') 除外,空格字符 (' ') 在用 isprint 检查时返回 true,但在使用 isprint 检查时返回 false。
tolower、toupper:转换大小写字母