前言:
C语言的标准库中有许多字符函数与字符串函数,其存在能够大大减轻许多编程压力,因此,充分了解并能够熟练运用字符函数与字符串函数是很有必要的,在本文中,我们将对于其进行深入了解
正文开始:
一.字符分类函数:
C语言中有一类函数专门用于字符分类,使用时需要包含一个头文件<ctype.h>
函数参数符合条件就返回真(非0)
具体函数如下:
1.iscntrl—任何控制字符
2.isspace—空白字符
3.isdigit—十进制数字
4.isxdigit—十六进制数字
5.islower—小写字母a-z
6.isupper—大写字母A-Z
7.isalpha—字母a-z或者A-Z
8.isalnum—字母或者数字
9.ispunct—标点符号,非任意字母(图形)或者数字
10.isgraph—任何图形字符
11.isprint—任何可打印字符,包括图形与空白字符
示例:
1.
#include<ctype.h>
int main()
{
int r = isdigit('a');//r=0;
printf("%d\n", r);
if (r)
{
printf("是十进制字符\n");
}
else
{
printf("不是十进制字符\n");
}
return 0;
}
输出结果为:
不是十进制字符
int main()
{
int r = islower('a');//r=2;
printf("%d\n", r);
if (r)
{
printf("是小写字符\n");
}
else
{
printf("不是小写字符\n");
}
return 0;
}
输出结果为:
是小写字符
int main()
{
//小写字符转大写
char arr[] = "I am a Chinese";
int i = 0;
for (i = 0; arr[i] != '\0'; i++)
{
int r=islower(arr[i]);
if (r)
{
arr[i] -= 32;//'a'-'A'=32
}
printf("%c", arr[i]);
}
return 0;
}
输出结果为:
I AM A CHINESE
二.字符转化函数
注:仅适用于字母
大写转小写:tolower
小写转大写:toupper
1次只能够转1个
示例:
int main()
{
//小写字符转大写
char arr[] = "I am a Chinese";
int i = 0;
for (i = 0; arr[i] != '\0'; i++)
{
int r = islower(arr[i]);
if (r)
{
arr[i] = toupper(arr[i]);
}
printf("%c", arr[i]);
}
return 0;
}
输出结果为:
I AM A CHINESE
字符转换函数的模拟实现:
以toupper函数为例:
char my_toupper(char x)
{
if (x >= 'a' && x <= 'z')
{
x -= 32;
}
return x;
}
int main()
{
//小写字符转大写
char arr[] = "i am a chinese";
int i = 0;
for (i = 0; arr[i] != '\0'; i++)
{
int r = islower(arr[i]);
if (r)
{
arr[i] = my_toupper(arr[i]);
}
printf("%c", arr[i]);
}
return 0;
}
该函数也能够行使字符转换功能
三.strlen函数
前面已讲,详情请看指针–习题练习
注:返回类型:size_t–无符号整型–必定大于等于0
示例:
int main()
{
if ((strlen("abc") - strlen("abcdef"))>0)
{
printf(">\n");
}
else
{
printf("<=\n");
}
return 0;
}
输出结果为
>
证明返回数字大于0,即为无符号整型
strlen函数的另一种模拟实现(第一种在指针–习题练习):
size_t my_strlen(const char* str)
{
if (*str != '\0')
{
return 1 + my_strlen(str + 1);
}
else
{
return 0;
}
}
四:字符串函数
1.strcpy
功能:字符串拷贝,拷贝到字符串中的\0为止
参数:两字符串的首元素地址
注:1.以\0结束
2.\0也会被拷贝
3.目标空间必须足够大
4.目标空间必须可被修改(即arr2初始化时不能是常量字符串)
示例:
i
nt main()
{
char arr1[] = "Hello world!";
char arr2[] = { 0 };
//arr2 = arr1;//错误!arr2代表地址,不可修改
//数组名为地址,地址是一个编号,但地址是常量,无法修改
char*ret= strcpy(arr2, arr1);
printf("%s\n", arr2);
printf("%s\n", ret);
return 0;
}
输出结果为:
Hello world!
Hello world!
strcpy函数的模拟实现:
两个条件:
1.能够将y代表数组的内容拷贝到x中
2.能够返回y数组的首元素地址
#include<assert.h>
char* my_strcpy(char* x, const char* y)
{
//x---指针,指向目的空间 //y--指针,指向源头数据
char* ret = x;
assert(y && x);//两者均不能为空指针
while (*x++ = *y++)
{
;
}
return ret;
}
int main()
{
char arr1[] = "Hello world!";
char arr2[20] = "xxxxxxxxx";
my_strcpy(arr2, arr1);
printf("%s\n", arr2);
return 0;
}
2.strcat–字符串追加
char* strcat(charx,const chary)
x----指针,指向目的空间
y–指针,指向源头数据
返回目标空间起始地址
注:
1.源字符串(x)必须以\0结束
2.目标字符串中也应有\0(从\0开始追加)
3.目标字符串应足够大,能够容纳源字符串内容
4.目标字符串可修改
示例:
int main()
{
char arr1[20] = "hello \0xxxxxxxx";
char arr2[] = "world!";
char*r=strcat(arr1, arr2);
printf("%s\n", arr1);
printf("%s\n", r);
return 0;
}
输出结果为:
hello world!
strcat函数的模拟实现:
两个条件:
1.能够将y代表数组的内容追加到x中
2.能够返回x数组的首元素地址
#include<assert.h>
char* my_strcat(char* x, char* y)
{
assert(y && x);
//1.寻找\0
char* r = x;
while (*x != '\0')
{
x++;
}
while (*x++ = *y++)
{
;
}
return r;
}
int main()
{
char arr1[20] = "hello \0xxxxxxxx";
char arr2[] = "world!";
char* r = my_strcat(arr1, arr2);
printf("%s\n", arr1);
printf("%s\n", r);
return 0;
}
3.strcmp—字符串比较
主要内容前面已讲
功能:从两个字符串首字母开始比较ASCII码值,若相同则比较下一字母
参数:char* a,char* b
返回值:a>b 返回t>0 a<b 返回t<0
示例:
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abq";
int r = strcmp(arr1, arr2);
printf("%d\n", r);
if (r < 0)
{
printf("arr1<arr2\n");
}
return 0;
}
输出结果为:
arr1<arr2
strcmp函数的模拟实现:
int my_strcmp(const char* a, const char* b)
{
assert(a && b);
while (*a == *b)
{
if (*a == '\0')
{
return 0;//相等
}
a++;
b++;
}
if (*a > *b)
{
return 1;
}
else
{
return -1;
}
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abq";
int r = my_strcmp(arr1, arr2);
printf("%d\n", r);
if (r < 0)
{
printf("arr1<arr2\n");
}
return 0;
}
输出结果一致!
另外:
介绍三个类似函数:
strncpy—strcpy
strncat—strcat
strncmp—strcmp
长度受限—长度不受限
前者相较于后者多出一个参数:size_t num,意义为限制拷贝的字符个数
主要优点:后者相较于前者更加灵活安全
示例:
int main()
{
char arr1[] = "abcdefg";//遇到\0提前结束
char arr2[] = "xxxxxxxxxxxx";
//strncpy(arr2, arr1, 5);//最多拷贝5个字符
//printf("%s", arr2);
//strncat(arr2, arr1, 5);//最多追加5个字符
//printf("%s", arr2);
int r=strncmp(arr2, arr1, 5);//最多比较5个字符
printf("%s\n", arr2);
printf("%d", r);//1---a>b
return 0;
}
其余内容重复,不再讲解
4.strstr函数
功能:在一个字符串中寻找另一个字符串第一次出现位置
结果:找到:返回出现位置指针,找不到:返回NULL
示例:
int main()
{
char arr1[] = "heheabcdefgh";
char arr2[] = "def";
char* p = strstr(arr1, arr2);
if (p != NULL)
{
printf("找到了,%s\n", p);//打印找到位置后的字符串
}
else
{
printf("未找到\n");
}
return 0;
}
strstr函数的模拟实现
两种:
1.
char* my_strstr(const char* a, const char* b)
{
char* p1 = a;
while (*p1 != *b)
{
p1++;
}
size_t len = 0;
char* p2 = b;
while (*b != '\0')
{
b++;
len++;
}
if (strncmp(p1, p2, len) == 0)
{
if (*p1 != '\0')
{
return p1;
}
else
{
return NULL;
}
}
else
{
return my_strstr(p1 + 1, b);
}
}
自己写的
char* my_strstr(const char* a, const char* b)
{
char* p = a;
char* s1 = NULL;
char* s2 = NULL;
//特殊场景:
if (*p == '\0')
{
return a;
}
while (*p)
{
s1 = p;
s2 = b;
while (*s1&&*s2&&*s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return p;
}
p++;
}
return NULL;
}
老师教的:暴力查找
其他方式:KMP
5.strtok函数
char * strtok(char * x,char * y)
功能:1.分割字符串;//根据y中的符号//调用一次分割一次
2.修改原始字符串,分割符号被修改为\0
3.返回首元素地址
示例:
int main()
{
char arr[] = "zpw@yeah.net";
char sep[] = "@.";
char buf[20] = { 0 };
strcpy(buf, arr);
char* p = NULL;
//1.
for (p = strtok(buf, sep); p != NULL; p = strtok(NULL, sep))
{
printf("%s\n", p);
}
//2.
//char* p = strtok(buf, sep);
//printf("%s\n", p);//zpw
//p = strtok(NULL, sep);//yeah
//printf("%s\n", p);
//p = strtok(NULL, sep);//net
//printf("%s\n", p);
//p = strtok(NULL, sep);//NULL
//printf("%s\n", p);
return 0;
}
6.strerror函数:
char*strerror(int errnum);
需要包含头文件<string.h>
C语言库函数在使用发生错误时会将一个错误码记录到errno的变量中
功能:
1.可以通过参数部分的errnum表示错误码,得到对应的错误信息,并返回错误信息字符串首字符地址
2.strerror函数只针对标准库中函数方式错误后设置错误码的转换
参数:errnum
示例:
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d:%s\n", i, strerror(i));
}//strerror函数将错误码转化为错误信息
return 0;
}
转换形式:
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
后面不再赘述
我们来看一个例子:
C语言可打开文件
该过程称为fopen
若以读的方式打开,则文件必须存在,若不存在,打开失败
open函数会将错误码放在errno中
同时函数返回NULL
如下:
int main()
{
FILE*pf=fopen("data.txt", "r");
if (pf == NULL)
{
printf("错误码为:\n%s\n", strerror(errno));
printf("该文件不存在,打开失败\n");
return 1;
}
//读文件:
//………………
//关闭文件:
fclose(pf);
pf = NULL;
return 0;
}
7.perror函数:
void perror(char*str);
功能:记录错误码+打印错误信息 一体化
perror(xxx) -->xxx:错误信息
缺点:不够灵活
优点:足够方便
具体功能前面已经分开介绍,故不再赘述
后记:
通过以上示例,我们对于字符与字符串函数有了一个较为系统的认识,通过不断进行练习,熟悉度也会提高,下一节我们将认识另一种新的C语言函数:内存函数。那么,本节内容到此结束,我们下节再见!
958

被折叠的 条评论
为什么被折叠?



