目录
前言
在我们进行编程的过程中,我们经常要处理字符和字符串,为了⽅便操作字符和字符串,C语⾔标准库中提供了 ⼀系列库函数,使用字符函数和字符串函数分别包含头文件 <ctype.h>和头文件<strling.h>。下面我就简单介绍一下常用的字符和字符串函数。
一、字符函数
C 语言中有一系列的函数是专门做分类的,简单来说就是判断这个字符是属于什么类型的,而使用这些函数都需要包含一个 下面我们就简单介绍一下这些函数(可点击直接跳跃查看具体介绍)
函数
所给参数若符合下列的条件,返回真
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 任何可打印字符,包括图形字符和空白字符 这些函数的使用方法非常类似,且较为简单,这里就不介绍了,大家可以直接点击这个函数去具体了解。
二、strlen函数
2.1 strlen 函数使用
strlen函数是用来求字符串长度的函数,返回 '\0' 之前字符的个数,不包含'\0'。size_t strlen ( const char * str ); strlen函数可以用来求字符串数组或者是字符串常量的长度,我们需要注意的是参数所指向的字符串必须要以'\0'结尾,不然所返回的值就是一个随机值,函数的返回值是size_t类型的,是为无符号。下面是使用代码
#include <stdio.h> #include <string.h> int main() { char arr1[] = "csdn";//存放 'c' 's' 'd' 'n' '\0'共五个字符 char arr2[] = { 'c','s','d','n','6' };//arr2数组中无'\0' char* p = "abcdef"; printf("%d\n", strlen(arr1));//返回4,strlen不统计'\0',但是以'\0'为结束标志 printf("%d\n", strlen(arr2));//返回值为随机值,每次运行结果都不一样 printf("%d\n", strlen(p));//返回6 return 0; }
2.2 模拟实现strlen函数
结合前面我们已经学过的知识,我们可以有多种方式来模拟实现strlen函数。在模拟实现之前我们先来思考一下strlen函数的具体细节,首先,strlen函数是以'\0'为结尾的,返回的参数类型是size_t类型,传递的参数是一个指针类型,所以在使用之前我们要用assert函数来断言一下是否指向NULL,而使用assert函数要包含头文件<assert.h>,下面我就以三种方式来模拟实现streln函数:
主函数
#include <stdio.h> #include <assert.h> //函数调用 int main() { char arr[] = "csdn666"; size_t n = Strlen3(arr); printf("%zd\n", n); return 0; }
方式一:计数器累加
//计数器累加 size_t Strlen1(const char* p) { size_t count = 0;//计数器初始值为0 assert(p != NULL);//断言所传递过来的地址是否为NULL while (*p)//所指向的不为'\0',进入while循环 { p++;//遍历数组或字符串常量 count++;//计数 } return count;//返回计数器的值 }
方式二:递归
//不使用临时变量,递归 size_t Strlen2(const char* p) { assert(p != NULL); if (*p == '\0')//直到遇到'\0'返回0 { return 0; } else//否则就递归 { return 1 + Strlen3(p + 1);//1+下一个字符的strlen函数 } }
方式三:指针相减
//指针相减 size_t Strlen3(const char* p) { assert(p != NULL); char* p0 = p;//将初始地址赋值给p0 while (*p) { p++; }//找到'\0'的地址 return p - p0;//两个地址相减即为字符的个数 }
二、长度不受限制的字符串函数
2.1strcpy函数
1. strcpy 函数
strcpy函数是字符串复制函数,char * strcpy ( char * destination, const char * source ); 其复制格式为将后一个source所指向的复制到前一个dest所指向的数组里,以 '\0' 为结束标志,会拷贝结束标志,函数最后返回dest的地址。需要注意的是,目标指向的应该为一个数组,允许修改,同时数组的大小应足够长,以确保能存放源字符串。
2. strcpy 函数的模拟实现
我们已经知道了strcpy函数是将一个字符串全部复制的另一个数组里,第一个参数是要复制到的地址,第二个参数是被复制的地址,复制过去的下标是从 0 开始的,从第一个字符开始复制,直到 '\0' ,一共有 n+1 个字符,所以所复制过去的数组的大小至少为 n+1 ,或者设置为足够大即可。这个函数的返回值为函数指针地址,那么在函数里面我们需要知道复制过去的函数的初始地址,下面是代码实现:
主函数:
#include <stdio.h> #include <assert.h> //Strcpy函数 int main() { char arr1[] = "csdn"; char arr2[10] = "666666666"; Strcpy1(arr2, arr1);//目标空间必须是可以修改的,不可以指向常量 printf("%s\n", arr2); return 0; }
普通方式:
//基础,最简单的 char* Strcpy1(char* p2, char* p1) { assert(p1 && p2); char* p = p2; while(*p1) { *p2 = *p1; p1++; p2++; } *p2 = '\0'; return p; }
优化后:
//进一步优化 char* Strcpy2(char* p2, char* p1) { assert(p1 && p2); char* p = p2; while (*p1) { *p2++ = *p1++;//先解引用,赋值,再加加 } *p2 = '\0'; return p; }
再优化
//再优化 char* Strcpy3(char* p2, char* p1) { assert(p1 && p2); char* p = p2; while (*p2++ = *p1++)//做条件,当p2值为\0时,结束 { ; } return p; }
运行结果:
可以看到当程序运行完后,arr2数组中的前5位都变了,其中arr2[4]的值为'\0',这证明了strcpy函数会一直复制,直到遇到'\0'结束,并将'\0'给复制过来。
2.strcat函数
1. strcat 函数
strcat函数是字符串追加函数,即在一个字符串的后面增添新的内容。其格式为char * strcat ( char * destination, const char * source );第一个参数为目标数组,第二个参数为源数组,返回类型为指针。要实现这个函数我们需要保证源字符串和目标字符串都必须以'\0'结束,这个可以直到从哪里开始追加,追加多少结束,同时还需要保证目标空间足够大,能够容纳源字符串的内容。
2. strcat 函数的模拟实现
通过上面的介绍,我们要实现strcat函数,首先要找到目标数组的结尾,然后将原数组开始从目标数组的'\0'位置开始复制追加,直到遇到源数组的'\0',然后返回目标数组的初始位置。下面我们就来实现这个函数:
#include <stdio.h> #include <assert.h> //两个函数追加,无法进行自我追加 char* Strcat(char* p1, const char* p2) { char* p = p1; assert(p1 && p2); while (*p1) { p1++; } while (*p1++ = *p2++) { ; } return p; } int main() { char arr1[20] = "csdn"; char arr2[20] = "6666"; Strcat(arr1, arr2); printf("%s\n", arr1); return 0; }
运行结果:
3.strcmp函数
1. strcmp 函数
strcmp函数是字符串比较函数,用于比较两个字符串的大小。其格式为int strcmp ( const char * str1, const char * str2 );这两个参数是两个字符串的地址,返回的是一个int型的数字。将字符串 str1 与字符串 str2 进行比较。此函数比较这两个字符串的每一个字符,如果当前字符相等,则继续比较下一个字符,直至比较出结果,第⼀个字符串⼤于第⼆个字符串,则返回⼤于0的数字 ;如果第⼀个字符串⼩于第⼆个字符串,则返回⼩于0的数字;或者是遇到null,则两个字符串相等,返回0。
2. strcmp 函数的模拟实现
因为我们比较的字符串,所以在函数里直接比较字符串里每一个字符的大小即可,同时要注意字符串是否结束,我写出了两种方法,一种是普通的循环,另一种则采用了递归,下面是实现的代码:
#include <stdio.h> #include <assert.h> //普通模式 int Strcmp1(const char * p1,const char * p2) { assert(p1 && p2); while (*p1 == *p2) { if (*p1 == '\0') return 0; p1++; p2++; } if (*p1 > *p2) return 1; else return -1; } //优化模式,递归 int Strcmp2(const char* p1, const char* p2) { assert(p1 && p2); while (*p1 == *p2) { if (*p1 == '\0') return 0; p1++; p2++; } return *p1 - *p2; } int main() { char arr1[] = "csdn66abc"; char arr2[] = "csdn66aaa"; int ret = Strcmp2(arr1, arr2); if (ret > 0) { printf("大于\n"); } else if (ret == 0) { printf("等于\n"); } else { printf("小于\n"); } return 0; }
三、长度受限制的字符串函数
1.strncpy函数
1. strncpy 函数
strncpy函数是一个字符串选择复制函数,和strcpy函数基本一样,但是这个函数多了一个参数,可以限制复制的字符的个数,其格式为char * strncpy ( char * destination, const char * source, size_t num );将源数字的的前num个字符复制到目标函数,如果在复制 num 个字符之前找到源 C 字符串的末尾(由 null 字符表示),则 destination 将用零填充,直到总共写入 num 个字符。如果 source 的长度大于 num,则不会在目标函数的末尾追加 null 字符。因此,在这种情况下,destination 不应被视为以 null 结尾的 C 字符串(这样读取它会溢出)。
2. strncpy 函数的模拟实现
strncpy函数实现和strcpy函数非常类似,就不具体说了,直接上代码:
#include <stdio.h> // 目的位置 从哪拷贝 拷贝个数 char* Strncpy(char* p2, char* p1, int n) { char* ret = p2; int i = 0; //拷贝的个数过多,超过数组的个数,所以 != '\0' // 且拷贝数量小于数组数,条件即为i<n for (i = 0; p1[i] != '\0' && i < n; i++) { p2[i] = p1[i]; } //在拷贝过程中不会拷贝'\0',需要手动拷贝 if (i < n) { p2[i] = '\0'; } return ret; } int main() { char arr1[20] = "csdn6789"; char arr2[20] = { 0 }; char* ret=Strncpy(arr2, arr1, 4); printf("%s\n",ret); return 0; }
2.strncat函数
1. strncat 函数
strncat函数是一个字符串选择追加函数,可以指定追加的个数,和strcat函数基本一样。其格式为char * strncat ( char * destination, const char * source, size_t num );将源数组的前 num 个字符附加到目标数组,外加一个终止 null 字符。如果 source 中 C 字符串的长度小于 num,则仅复制终止 null 字符之前的内容。
2. strncat 函数的模拟实现
strncat函数的实现和strcat函数非常类似,就不具体说了,直接上代码:
#include <stdio.h> // 目的位置 从哪拷贝 拷贝个数 char* Strncat(char* p2, char* p1, int n) { //记录拷贝到的初始位置 char* ret = p2; //找到'\0'的位置 while (*p2!='\0') { p2++; }//此时p2所指向的位置就是arr2中'\0'的地址 int i = 0; //for循环拼接,拼接的个数小于n个,且第n个不为'\0' for (i = 0; i < n && p1[i] != '\0'; i++) { p2[i] = p1[i]; } //当所要拼接的字符串的个数小于n时,末尾手动赋值'\0' if (i < n) { p2[i] = '\0'; } //返回拼接到的函数的初始地址 return ret; } int main() { char arr1[20] = "csdn"; char arr2[20] = "123456"; char* ret = Strncat(arr2, arr1, 6);//接收初始地址 printf("%s\n", ret);//打印 return 0; }
3.strncmp函数
1. strncmp 函数
strncmp函数是字符串选择比较函数,可以限定比较字符串的个数。其格式为:int strncmp ( const char * str1, const char * str2, size_t num );其实现过程是将字符串str1和str2的字符数进行比较,从第一个开始,如果相等则继续向下比较,直至字符不相等或者到达限定的个数,返回相应的结果。
2. strncmp 函数的模拟实现
strncmp函数的实现和strcmp函数非常类似,就不具体说了,直接上代码:
#include <stdio.h> #include <assert.h> //以null结尾的字符串 const修饰防止字符串被修改,进行保护 int Strncmp(const char* p1, const char* p2, int n) { assert(p1 && p2); if (!n) //n=0时,无字符要比,直接返回0 return 0; while (--n && *p1 && *p2 == *p1) //当字符相等且不为’\0‘时比较下个字符 { p2++; p1++; } return *p1 - *p2;//字符不相等时,采用递归相减 } int main() { char arr1[] = "csdn66a"; char arr2[] = "csdn66b"; int ret = Strncmp(arr1, arr2,8); if (ret > 0) { printf("大于\n"); } else if (ret == 0) { printf("等于\n"); } else { printf("小于\n"); } return 0; }
四、字符串查找
1.strstr函数
1. strstr 函数
strstr函数是查找子字符串函数,是在一个字符串中查找是否有另一个字符串。其格式为const char * strstr ( const char * str1, const char * str2 );返回指向 str2 中第一次出现的 str1 的指针,如果 str2 不是 str1 的一部分,则返回一个 null 指针。匹配过程不包括终止 null 字符('\0'),但它会停止到此为止。
2. strstr 函数的模拟实现
strstr函数还是比较容易理解的,代码里面有注释,话不多说直接上代码
#include<stdio.h> #include<string.h> char* Strstr(const char* str1, const char* str2) { const char* p = str1;//程序运行过程中会改变数组的地址,采用变量来进行计算 const char* s2 = str2; const char* s1 = str1; if (str2 == NULL)//如果子字符串地址为空 { return (char*)str1;//返回str1 } while (*p)//当str1当前值不为'\0'时 { s2 = str2;//每次循环之后都初始为str2的地址 s1 = p;//s1同样 while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2)//解引用str1,str2不为0且相等 { s1++; s2++; } if (*s2 == '\0')//若str2当前的值为0 { return (char*)p;//返回从p地址开始往后的str1 } p++;//p++,str1向后比较 } return NULL; } int main() { char arr1[10] = { "abcddEFgh" }; char arr2[4] = { "bcd" }; char* p = Strstr(arr1, arr2); if (p == NULL) { printf("找不到子字符串\n"); } else { printf("%s\n", p); } return 0; }
2.strtok函数
1. strtok 函数
strtok函数是将字符串拆分为标记函数,其格式为:char * strtok ( char * str, const char * delimiters );对此函数的一系列调用将str拆分为标记,这些标记是由分隔符中的任何字符分隔的连续字符序列。在第一次调用时,该函数需要一个 C 字符串作为 str 的参数,str的第一个字符用作扫描令牌的起始位置。在后续调用中,该函数需要一个 null 指针,并使用最后一个标记末尾之后的位置作为扫描的新起始位置。
为了确定标记的开头和结尾,该函数首先从起始位置扫描分隔符中未包含的第一个字符(该字符成为标记的开头)。然后从标记的开头开始扫描分隔符中包含的第一个字符,该字符成为标记的末尾。如果找到终止 null 字符,扫描也会停止。strtok函数的第⼀个参数不为 NULL ,函数将找到str中第⼀个标记,strtok函数将保存它在字符串 中的位置。strtok函数的第⼀个参数为 NULL ,函数将在同⼀个字符串中被保存的位置开始,查找下⼀个标记。在对 strtok 的调用中找到 str 的终止 null 字符后,对此函数的所有后续调用(以 null 指针作为第一个参数)将返回 null 指针。
2. strtok 函数的使用
这个就不模拟实现了,直接上使用的代码
#include <stdio.h> #include <string.h> int main() { char arr1[] = "1666888999@qq.com"; char arr2[20] = { 0 }; strcpy(arr2, arr1); const char* p = "@."; //采用for循环优化 char* s = NULL; //利用for循环初始化值只执行一次 for (s = strtok(arr2, p); s != NULL; s = strtok(NULL, p)) { printf("%s\n", s); } return 0; }
运行结果
3.strerror函数
1. strerror 函数
strerror函数是一个获取指向错误消息字符串的指针的函数,其格式为为:char * strerror ( int errnum );strerror函数可以把参数部分错误码对应的错误信息的字符串地址返回来。
在不同的系统和C语⾔标准库的实现中都规定了⼀些错误码,⼀般是放在 errno.h 这个头⽂件中说明 的,C语⾔程序启动的时候就会使⽤⼀个全⾯的变量errno来记录程序的当前错误码,只不过程序启动 的时候errno是0,表⽰没有错误,当我们在使⽤标准库中的函数的时候发⽣了某种错误,就会讲对应 的错误码,存放在errno中,⽽⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是 有对应的错误信息的。strerror函数就可以将错误对应的错误信息字符串的地址返回。
2. strerror 函数的使用
这个就不模拟实现了,直接上使用的代码
#include <stdio.h> #include <string.h> #include <errno.h> int main() { FILE* pfile; pfile = fopen("unexit.txt", "r"); if (pfile == NULL) //printf("错误是:%s\n", strerror(errno)); perror("错误是"); else printf("打开文件成功\n"); } //常用错误序号 //0 : No error //1 : Operation not permitted //2 : No such file or directory //3 : No such process //4 : Interrupted function call //5 : Input / output error //6 : No such device or address //7 : Arg list too long //8 : Exec format error //9 : Bad file descriptor //10 : No child processes
运行结果
五、总结
以上就是今天的全部内容了,主要是介绍了一些字符和字符串相关的函数,种类还是挺多的,可以仔细看一看。如有不足欢迎家人们评论区批评指正,如果这篇文章对你有用的话,可以给我来个一键三连嘛