往期回顾:
【C语言】带你手撕字符函数和字符串函数(1)(内含部分库函数模拟实现)
这篇文章我们将一起来学习字符串查找函数、错误信息报告、字符操作函数以及内存操作函数。
1 strstr
1.1 strstr的定义
strstr是用来查找字符串位置的,按照如下的定义,它的作用是在str1中寻找str2第一次出现的地址。
当str2在str1中出现多次时,只返回第一次出现的地址
当str2没有在str1中出现时,返回空指针

与其类似的函数还有:
strchr:在字符串中寻找指定字符第一次出现的位置;
strrchr:在字符串中寻找指定字符最后一次出现的位置
1.2 模拟实现strstr
char* my_strstr(const char* str1, const char* str2)
{
char* cp = (char*)str1;
char* s1, *s2;
if (!*str2)
return ((char*)str1);
while (*cp)
{
s1 = cp;
s2 = (char*)str2;
while (*s1 && *s2 && !(*s1 - *s2))
{
s1++;
s2++;
}
if (!*s2)
return cp;
cp++;
}
}
2 strtok
2.1 strtok的定义
strtok是字符串分隔函数,定义如下:

delimiters是一个字符串,存放的是用作分隔符的字符集和
第一个参数指定一个字符串,包含了0个或者多个由delimiters中一个或者多个分隔符分隔的标记
strtok函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针(分隔符所分隔出的字符串的起始地址)
如果strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保留他在字符串中的位置(相当于记忆功能)
如果strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记
如果字符串中不存在更多的标记,则返回NULL指针
strtok函数会改变被操作的字符串,所以在使用strtok函数时,一般会临时拷贝一份可修改的字符串,以此保护源字符串
2.2 strtok使用实例
下面是strtok的一个简单应用:
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "HelloWorld@qq.com";
char tok[] = "@.";
char* pch = strtok(str, tok);
while (pch != NULL)
{
printf("%s\n", pch);
pch = strtok(NULL, tok);
}
return 0;
}
这个模板也是strtok的一个常规使用模板。
可以简单理解为,strtok在第一次使用时需要传递指定字符串和分割字符串的地址。
当需要连续分割时,就需要将第一个参数置为NULL,让函数从上一次被保存的位置开始继续寻找,如果找不到就返回空指针。
也可使用for循环:
int main()
{
char str[] = "HelloWorld@qq.com";
char tok[] = "@.";
char* pch =NULL;
for (pch = strtok(str, tok); pch != NULL; pch = strtok(NULL, tok))
{
printf("%s\n", pch);
}
return 0;
}
3 strerror
3.1.strerror的定义
strerror是用来报告错误信息的,定义如下

作用是返回错误码所对应的错误信息。
什么是错误码呢?
错误码可以理解为C语言的一种异常情况处理机制。当程序执行过程中出现了一些错误,就会返回一个错误码,而strerror函数就可以通过错误码翻译出出错误码所对应的错误信息,并且返回该错误信息所对应的字符串的起始地址。
可以将错误码理解为将复杂的错误信息简单化的编码。
错误码在C语言中有专门的一个变量储存errno
3.2 strerror使用实例
来看一个演示:

这个案例比较直观的展现了strerror对于错误码的解析。
实际上strerror函数并不是这么用的,在cplusplus网站上给出了一个使用实例:
#include <stdio.h>
#include <string.h>
#include <errno.h> //这个是包含strerror的头文件,使用strerror时必须包含
int main ()
{
FILE * pFile;
pFile = fopen ("unexist.ent","r");
if (pFile == NULL)
printf ("Error opening file unexist.ent: %s\n",strerror(errno));
return 0;
}

可以看出该程序的错误信息是没有找到匹配的文件,那是因为我的计算机上没有unexist.ent这个文件,因此编译器在按照执行过程中发现无法继续执行,于是返回一个错误码,而通过strerror就可以将这个错误码翻译出来。
3.3 strerror的高级替换——perror
strerror函数仅仅是将错误码翻译成错误信息,并且返回错误信息所对应字符串的起始地址。而我们想要知道具体错误信息的话,就需要将其打印在屏幕上,那就需要与printf配合使用,这样显得有些麻烦。
perror是这样一个函数:在strerror的基础上,还可以自动打印错误信息,相当于strerror+printf的一个复合函数,相当高级。

来看看perror是如何“高级”的:
#include <errno.h>
int main()
{
FILE* pFile;
pFile = fopen("unexist.ent", "r");
if (pFile == NULL)
perror("打开文件失败");
return 0;
}

我们仅仅在perror中设置了一个字符串作为参数,而perror自动在我们所添加的字符串后面加上了一个分号':',并且自动打印了错误信息
perror("打开文件失败")与printf ("Error opening file unexist.ent: %s\n",strerror(errno))
这两条语句是等价的,但是perror更加容易了解,同时也更加简洁
4 字符分类函数和字符转换函数
4.1 字符分类函数
顾名思义,字符分类函数就是用来给字符分类的

4.2 字符转换函数
最常用的就是大小写转换:
int tolower(int c) 转换为小写
int toupper(int c) 转换为大写
(注:通过ASCII码值转换,所以类型为int)
4.3 使用实例
关于字符分类和字符转换函数看一个实例就能很好地理解
(注:两类函数在使用时都需要包含头文件<ctype.h>)
#include <stdio.h>
#include <ctype.h>
int main()
{
int i = 0;
char str[] = "Test String.\n";
char c;
while (str[i])
{
c = str[i];
//如果c是大写字母,则转换为小写字母
if (isupper(c))
c = tolower(c);
putchar(c);
i++;
}
return 0;
}
运行结果:

(本篇完)