今天我们接着讲字符串函数,也会讲到字符函数。关于下面的字符串函数我们将从:作用 头文件 参数返回值 等方面去介绍。🆗🆗
字符串查找
strstr
- strstr_string string库函数,是在字符串中找字符串
- const char * strstr ( const char * str1, const char * str2 ); 本质上就是在str1去查找str2,strstr会返回str1中str2第一次出现的位置,如果str1中没有str2,返回NULL
- 头文件#include
- 参数:两个字符串的指针
- 返回值:str1中str2第一次出现的位置
- strstr的模拟
strstr的使用
#include<stdio.h> #include<string.h> int main() { char arr1[] = "abcdefdhidefghi"; char arr2[] = "def"; const char* ret=strstr(arr1, arr2); //arr2第一次出现的位置 if (ret == NULL) printf("找到不到"); else printf("%s", ret); return 0; }
strstr的模拟实现
分析
在我们的arr1中查找arr2中有很多种情况如下图:
当然最后一种情况我们还可以分为比较复杂的情况如下图:
考虑点
所以综上我们需要考虑:
- str1和str2一开始就为空情况
- 在遍历过程中*s1为'\0' *s2为'\0'情况
- 创建str1和str2去记录 记录arr1和arr2的起始位置
- 创建s1和s2去遍历查找匹配比较
- 创建cp为了记录可能匹配成功的arr1中arr2第一次出现位置的地址
- 两个循环条件
- 当情况比较复杂的时候,请不要改变字符串起始位置的指针变量,创建其他的指针去查询。
- const
- assert
代码
#include<stdio.h> #include<string.h> const char* my_strstr(const char* str1, const char* str2) { const char* cp;//记录开始匹配的位置,可能arr1中arr2第一次出现的位置 const char* s1;//遍历str1指向的字符串 const char* s2;//遍历str2指向的字符串 //char*str1; //char*str2; assert(str1 && str2); cp = str1;//不改变初始位置的值 while (*cp)//等于'\0'返回NULL { s1 = cp;//不改变cp的值 s2 = str2;//不改变str2的值 while (*s1 && *s2 && *s1 == *s2) //*s1 =='\0',arr1提前遇到'\0'找到不到了返回null //*s2 == '\0'arr2全部遍历匹配成功,返回此刻的cp //== 相等进入循环开始遍历匹配比较 { s1++; s2++; //直到它们不相等跳出循环,找到下一个cp的位置继续查询 } if (*s2 == '\0') return cp; //*s2 arr2全部匹配成功遇到'\0' //一开始*str2 == '\0' cp++; } return NULL; //一开始*str1 == '\0' //*s1 中途遇到'\0'(即arr1长度<arr2) //arr1全部遍历完也没有匹配的 } int main() { char arr1[] = "abbbcdef"; char arr2[] = "bbc"; const char* ret = my_strstr(arr1, arr2); //arr2第一次出现的位置 if (ret == NULL) printf("找不到"); else printf("%s", ret); return 0; }
#include<stdio.h> #include<string.h> const char* my_strstr(const char* str1, const char* str2) { const char* cp; const char* s1; const char* s2; assert(str1 && str2); cp = str1; while (*cp) { s1 = cp; s2 = str2; while (*s1 && *s2 && *s1 == *s2) { s1++; s2++; } if (*s2 == '\0') return cp; cp++; } return NULL; } int main() { char arr1[] = "abbbcdef"; char arr2[] = "bbc"; const char* ret = my_strstr(arr1, arr2); if (ret == NULL) printf("找不到"); else printf("%s", ret); return 0; }
strt
tsqxgd@yeah.net 192.168.101.23// IP地址_点分十进制的表示方法 //IP地址本来是一个无符号的整数,这种整数不方便记忆,所以将这个整数换成点分十进制的表示方法 分割符: "@."//不讲究顺序 "."
char * strtok ( char * str, const char * sep );
- 第二参数char *sep参数是个字符串,定义了用作分隔符的字符集合
- 第一个参数char * str指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
- 头文件:#include
- 有可分割的字符串返回标记的指针
- 无可分割的字符串返回NULL
- 分割过程:
- strtok函数找到str中的一个标记。
- 利用sep找到这个标记的分隔符,并将标记用 \0 结尾(将标记末尾的分隔符改变成'\0')
- 返回一个指向这个标记的指针
- 保存这个标记在字符串中的位置(以方便分割下一个标记)。
- 特别注意:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。
- strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
- strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
- 如果字符串中不存在更多的标记,则返回 NULL 指针。停止分割
- 因为切割字符串的过程中会改变原字符串的内容,所以我们可以先拷贝到临时空间,再对临时空间进行拷贝。
- 若分割符和分割符相邻,会跳过。
- 那到底strtok是怎样保存标记在字符串的位置呢?可能是static
strtok的使用
#include<stdio.h> #include<string.h> int main() { char arr[] = "tsqxgd@yeah.net"; char buf[200] = { 0 };//放到临时的空间里,防止原arr被改变 strcpy(buf, arr); char* sep = "@."; char* ret = strtok(buf, sep); printf("%s\n", ret); ret = strtok(NULL, sep); printf("%s\n", ret); ret = strtok(NULL, sep); printf("%s\n", ret); return 0; }
循环改进
#include<stdio.h> #include<string.h> int main() { char arr[] = "tsqxgd@yeah.net"; char buf[200] = { 0 };//放到临时的空间里,防止原arr被改变 strcpy(buf, arr); char* sep = "@."; char* ret = NULL;//ret为空 for (ret = strtok(buf, sep); ret != NULL; ret=strtok(NULL, sep)) { printf("%s\n", ret); } return 0; }
错误信息报告
strerror
strerror - C++ Reference (cplusplus.com)
- strerror是库函数,将错误码翻译成错误信息,返回错误信息的字符串的起始地址
- 头文件:#include
- 参数:错误码(整型)
- 返回值:返回错误信息的字符串起始地址
- C语言中使用库函数的时候,如果发生错误,就会将错误码放在errno的变量中。
- errno是一个全局变量,可以直接使用
char * strerror ( int errnum );
错误码的错误信息
/* strerror example : error list */ #include <stdio.h> #include <string.h> #include <errno.h>//必须包含的头文件 int main() { int i = 0; for (i = 0; i < 10; i++)//错误码 { printf("%d:%s\n", i, strerror(i));//错误信息 } return 0; }
strerror的使用
那上面只是我们查看一下各个错误码对应的错误信息,那在具体的情况下,我们应该怎样使用呢?
/* strerror example : error list */ //打开文件的例子 //foopen以读的形式打开文件 //如果文件存在,打开成功 //如果文件不存在,打开失败 #include <stdio.h> #include <string.h> #include <errno.h>//必须包含的头文件 int main() { FILE* pFile; pFile = fopen("unexist.ent", "r"); if (pFile == NULL) printf("打开文件失败原因是: %s\n", strerror(errno)); else printf("打开文件成功\n"); return 0; }
perror
perror - C++ Reference (cplusplus.com)
- 直接打印错误码所对应的错误信息
- perror == printf +strerror
//打开文件的例子 //foopen以读的形式打开文件 //如果文件存在,打开成功 //如果文件不存在,打开失败 #include <stdio.h> #include <string.h> #include <errno.h>//必须包含的头文件 int main() { FILE* pFile; pFile = fopen("unexist.ent", "r"); if (pFile == NULL) perror("打开文件失败"); //== printf+strerror else printf("打开文件成功\n"); return 0; }
字符操作
字符分类函数
关于字符分类函数我们就不一一讲解,大家通过查询网站,和从参数,返回值等方面去分析这些函数。注意字符函数的头文件是#include
(ctype.h) - C++ Reference (cplusplus.com)
中文表格
字符转化函数
(ctype.h) - C++ Reference (cplusplus.com)
#include <stdio.h> #include <ctype.h> int main() { int ret = toupper('a'); printf("%c\n", ret); ret = tolower(ret); printf("%c\n", ret); return 0; }
我们用字符转化函数来实现一个简单的功能吧🆗🆗
将arr字符串数组中的大写转化成小写
#include <stdio.h> #include <ctype.h> int main() { char arr[] = "Text String"; //全部转化成小写 int* p = arr; while (*p) { if (isupper(*p)) { *p = tolower(*p); } p++; } printf("%s", arr); return 0; }
char类型可以放到int类型的变量中去;
但是int类型不可以放到char类型的变量中去
✔✔✔✔✔最后,感谢大家的阅读,若有错误和不足,欢迎指正!下篇博文我们介绍内存函数。
希望我们都能够熠熠生辉,旗鼓相当。
代码------→【gitee:唐棣棣 (TSQXG) - Gitee.com】
联系------→【邮箱:2784139418@qq.com】