在今天的文章里,我将对字符串函数进行最后阶段的介绍,相信过了今天,你对字符串函数的了解将会更加深入。
strtok函数
由msdn查询可以得知,该函数的参数类型和返回类型是:
char* strtok(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.如果字符串中不存在更多的标记,则返回空指针。
我直接举个strtok函数的使用例子。
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "123456789@qq.com"; //包含了0个或者多个由分隔符的字符串中的一个或者多个分隔符分割的标记。
char arr2[] = "@."; //由分隔符组成的字符集合。
char* p = NULL;
p = strtok(arr1,arr2); //第一个参数第一次使用时传arr1字符串
printf("%s\n",p);
p = strtok(NULL,arr2); //第一个参数第二次使用时传NULL
printf("%s\n",p);
p = strtok(NULL,arr2); //第一个参数第三次使用时传NULL
printf("%s\n",p);
return 0;
}
运行结果如下:
由上面的一个小程序可以发现,strtok函数主要在str参数中寻找与sep参数相同的字符,将这些与sep参数相同的字符剔除掉,并返回那些与sep参数不相同的字符。
如果我们在使用strtok函数中,跟上面的小程序一样写的话,是比较低效的,我将对上面的代码进行改进。
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "123456789@qq.com";
char arr2[] = "@.";
char* str = NULL;
for(str = strtok(arr1,arr2);str != NULL;str = strtok(NULL,arr2)) //第一次使用时往第一个参数传参arr1,其他时候传参NULL
{
printf("%s\n",str);
}
return 0;
}
运行结果如下;
相比第一次的代码,第二次代码看起来更加的简洁,我们以后对于strtok函数的使用时,尽量使用第二种写法。
接下来,我对strtok函数进行模拟实现。
#include<stdio.h>
#include<string.h>
#include<assert.h>
char* my_strtok(char* str,const char* sep)
{
static char* s1 = NULL;
static char* s2 = NULL;
static int len1 = 0;
static int count = 0;
int len2 = 0;
int i = 0;
assert(sep != NULL);
if(str != NULL) //第一次进入
{
s1 = str; //s1记住初始位置
len1 = strlen(str);
len2 = strlen(sep);
for(*str;*str != '\0';str++) //移动str参数
{
for(i=0;i<len2;i++) //i为移动sep参数做准备
{
if(i == 0)
{
count++;
}
if(*str == *(sep+i)) //比较str字符串和sep字符串
{
*str = '\0'; //相同赋值为'\0'
s2 = str; //s2作为跳板
return s1;
}
}
}
}
else
{
s1 = s2 + 1; //s2作为跳板,s1记住初始位置
len2 = strlen(sep);
str = s1; //这一次str为NULL,所以要对str赋值
for(*str;*str != '\0';str++) //移动str参数
{
for(i=0;i<len2;i++) //为移动sep参数做准备
{
if(i == 0)
{
count++;
}
if(*str == *(sep+i)) //比较str参数和sep参数
{
*str = '\0'; //str参数和sep参数相同就赋值为'\0'
s2 = str;
return s1;
}
}
}
}
if(count > len1)
{
return NULL;
}
return s1;
}
int main()
{
char arr1[] = "123456789@qq.com";
char arr2[] = "@.";
char* str = NULL;
for(str = my_strtok(arr1,arr2);str != NULL;str = my_strtok(NULL,arr2))
{
printf("%s\n",str);
}
return 0;
}
由运行结果可以得知,strtok函数的模拟符合strtok函数的功能。
strerror函数
由msdn查询可以得知,strerror函数的返回类型和参数类型是:char* strerror(int errnum)。
这个函数是用于返回errnum所对应的错误信息的,而这些错误信息是C语言中库函数报错的时候的错误码。
如下面这个例子:
#include<stdio.h>
#include<string.h>
int main()
{
printf("%s\n",strerror(0));
printf("%s\n",strerror(1));
printf("%s\n",strerror(2));
printf("%s\n",strerror(3));
printf("%s\n",strerror(4));
return 0;
}
运行结果如下:
这个程序打印的是错误码的内容,如错误码1对应的是运行结果的第一条,错误码2对应运行结果2的第二条。
错误码的信息一般储存在errno变量中,头文件为errno.h。
如:
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<errno.h>
int main()
{
//以阅读的方式打开文档
FILE* pf = fopen("text.txt","r");
if(pf == NULL)
{
printf("%s\n",strerror(errno));
return 1;
}
//使用
//释放
fclose(pf);
pf = NULL;
return 0;
}
在这个程序中,我打开一个不存在的文档,失败的话,错误码就会被保存在errno变量中,然后用strerror函数进行解析错误码,最后用printf函数打印错误信息。
由运行结果可以得知,程序的确与我们的猜想一样。那么,这个错误码信息什么意思呢?翻译一下就行了嘛,没有这个文件或文件夹。
对于错误码的解析函数,还有另外一个较为重要的函数,那就是perror函数,头文件是stdio.h。
我将上面的代码进行略微改动。
#include<stdio.h>
#include<assert.h>
#include<string.h>
#include<errno.h>
int main()
{
//以阅读的方式打开文档
FILE* pf = fopen("text.txt","r");
if(pf == NULL)
{
perror("error");
return 1;
}
//使用
//释放
fclose(pf);
pf = NULL;
return 0;
}
在上面的代码中,我将printf函数换成perror函数,perror函数包含了解析错误码和打印错误信息的功能。
由运行结果可知,错误信息多了个error:
我在上面代码中,对于perror函数是这样写的perror("error")
,由此可以得知,perror会输出:传参信息+冒号+错误信息。
当然,我们可以不往perror函数传参,如:perror(“”)
,虽然有的编辑器不会报错,但是我们尽量不这样写,因为这样写是不符合perror的语法规则的。
字符分类函数介绍(头文件是:ctype.h。)
函数 | 如果他的参数符合下列条件就返回真 |
---|---|
iscntrl | 任何控制字符 |
isspace | 空白字符:空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’ |
isdigit | 十进制数字 0~9 |
isxdigit | 十六进制数字,包括所有十进制数字,小写字母a到f,大写字母A到F |
islower | 小写字母a~z |
isupper | 大写字母A~Z |
isalpha | 字母az或AZ |
isalnum | 字母或者数字,az,AZ,0~9 |
ispunct | 标点符号,任何不属于数字或者字母的图形字符(可打印) |
isgraph | 任何图形字符 |
isprint | 任何可打印字符,包括图形字符和空白字符 |
例子:
#include<stdio.h>
#include<ctype.h>
int main()
{
char ch = 'a';
int ret = isdigit(ch);
printf("%d\n",ret);
return 0;
}
如上面判断是不是数字字符,是就返回非0,不是就返回0。
字符转换函数(头文件是:ctype.h。)
函数 | 作用 |
---|---|
tolower | 大写字母转小写 |
toupper | 小写字母转大写 |
例子:
#include<stdio.h>
#include<ctype.h>
int main()
{
char ch = 'w';
printf("%c\n",toupper(ch));
return 0;
}
如上面的toupper函数一样,将字符’w’转换为’W’。
直到今天,字符串函数终于讲完了,如果感觉对你有用的话,那么就关注点一点,下期更精彩。