字符函数
1.字符分类函数
需要包含头文件ctype.h
不使用字符函数写的程序
利用字符函数写的程序
2.字符转换函数
int tolower ( int c ); //将参数传进去的⼤写字⺟转⼩写
int toupper ( int c ); //将参数传进去的⼩写字⺟转⼤写
字符串函数
1.strlen的使用和模拟实现
字符串以 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前⾯出现的字符个数(不包含 ‘\0’ )
• 参数指向的字符串必须要以 ‘\0’ 结束。
• 注意函数的返回值为size_t,是⽆符号的( 易错 )
• strlen的使⽤需要包含头⽂件
• 学会strlen函数的模拟实现**
返回类型是无符号的
运行结果错误,应该是<=
强制类型转换就OK了
模拟实现——计数器、递归
1.计数器
2.递归
如果不等于\0,说明字符串长度至少为1
所以这样递归
在每一次递归调用中,都会检查当前字符是否是结束符,如果不是,则继续递归调用直到找到结束符
通过递归调用,函数可以顺序地遍历字符串中的每个字符,直到找到结束符为止,从而计算出字符串的长度
2.strcpy的使用和模拟实现——字符串拷贝
char* strcpy(char * destination, const char * source );
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "hello word";
//字符串拷贝到arr2
char arr2[20] = { 0 };
strcpy(arr2,arr1);
printf("%s", arr2);
return 0;
}
这个警告代码要放到第一行才行
验证\0是否被拷贝过去
%s遇到\0不会继续打印,遇到\0就停下,所以后面的几个x没有打印
更严谨一点的版本
#include<string.h>
#include<stdio.h>
void my_strcpy(char* dest, const char* src)
{
assert(src != NULL);
assert(dest!= NULL);
//拷贝\0前面的内容
while (*src!='\0') {
*dest = *src;
dest++;
src++;
}
*dest = *src;//拷贝\0
}
int main()
{
char arr1[] = "hello word";
char arr2[20] = {"xxxxxxxxxxxx"};
my_strcpy(arr2,arr1);
printf("%s", arr2);
return 0;
}
更好的写法
#include<string.h>
#include<assert.h>
#include<stdio.h>
char* my_strcpy(char* dest, const char* src)
{
assert(src != NULL);
assert(dest!= NULL);
char*ret=dest;//把dest的值存起来
//拷贝\0前面的内容
while (*dest++ = *src++)//拷贝给dest,字符h,一直到\0, 既拷贝了又判断了,到\0的ASCII是0,就停止循环
{
;
}
return ret;
}
int main()
{
char arr1[] = "hello word";
char arr2[20] = {"xxxxxxxxxxxx"};
my_strcpy(arr2,arr1);
printf("%s", arr2);
return 0;
}
3.strcat的使用和模拟实现——用来连接字符串
char*strcat (char*dest,const char*src)
要保证目标空间足够大,也就是上面arr1的空间足够大,连接过去有空间
如何模拟实现——my_strcat
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<assert.h>
//返回的是目标空间的起始地址
char* my_strcat(char*dest,const char*src)
{
//assert(dest!=NULL);
//assert(src!=NULL);//空指针为0
assert(dest && src);
char* ret=dest;//后面dest一直在自增,存放一下原来的dest
//1.找到目标空间的\0 遍历数组1,找到杠零
while (*dest != '\0')
{
dest++;
}//2.找到后拷贝
while (*dest++ = *src++)//拷贝进去,一直向后
{
;//需要有语句,但什么都不用干,空语句
}
return ret;
}
int main()
{
char arr1[20] = "hello ";//我想让他打印出hello world
//连接字符串
char arr2[] = "world";
char*s=my_strcat(arr1, arr2);//2连接到1,打印1
printf("%s\n", arr1);
printf("%s\n", s);
return 0;
}
运行结果:
能自己连接自己吗?——不可以\0会被掩盖导致死循环
my_strcat(arr1,arr1);//写法错误,会死循环
4.strcmp的使用和模拟实现———比较两个字符串的内容
int strcmp(const char*str1,const char*str2)
两个字符内容相等,返回0
大于,返回>0;小于,返回<0
模拟实现代码
#include<assert.h>
int my_strcmp(const char*str1,const char*str2)
{
assert(str1 && str2);
while (*str1 == *str2)
{
if (*str1 == '\0')
return 0;
str1++;
str2++;
}
if (*str1 > *str2)
{
return 1;
}
else {
return -1;
}
}
int main()
{
char arr1[] = "abq";
char arr2[] = "abcdef";
int ret =my_strcmp(arr1, arr2);
printf("%d\n", ret);
return 0;
}
介绍完前三个,现在来介绍后三个
1.strncpy的使用和模拟实现
char*strncpy (char*dest,const char*src,size_t num)
strncpy比strcpy多了一个参数num
num表示拷贝几个——限制长度
num——src里最多要拷贝几个
1拷贝到2里面3个字符
arr1只有6个字符,我下面要求给我拷贝过去8个,非常重视num,不够后面2个就用\0代替
2.strncat——追加num个字符
char*strncat(char*dest,const char*src,size_t num)
一样也是多了一个num
strncat追加过后会添加\0,保证追加完之后还是个字符串
这点就和strncpy不同,strncpy在num足够的情况下不会追加\0的,num太大了,拷贝的个数不够才会追加\0
如果num太大,字符个数不够用,strncat会追加\0来代替吗?——不会
strncat不够重视num不会补\0
我们这里就是做些简单的比较,对于num的取值没有那么随意
比如
int main()
{
char arr1[] = "abcdef";
char arr2[20] ="xx\0";
int len = strlen(arr1);
strncat(arr2, arr1,len );
printf("%s", arr2);
return 0;
}
我们对于num的取值,一般是这样计算的(要拷贝的字符的长度)
3.strncmp——最多比较num个字符
也是多了一个参数
int strncmp(const char*str1,const char*str2,size_t num)
最多比较num个,比如前三个就能比较出来,就不会向后比较了
模拟实现
//模拟实现
#include<assert.h>
int my_strcmp(const char*str1,const char*str2)
{
assert(str1 && str2);
while (*str1 == *str2)
{
if (*str1 == '\0')
return 0;
str1++;
str2++;
}
if (*str1 > *str2)
{
return 1;
}
else {
return -1;
}
}
int main()
{
char arr1[] = "abq";
char arr2[] = "abcdef";
int ret =my_strcmp(arr1, arr2);
printf("%d\n", ret);
return 0;
}
在使用VS2022是有时会提醒XXX不够安全,需要在第一行加上#define _CRT_SUCURE_NO_WARNINGS,一定是在第一行加上
4.strstr——在一个字符串中查找另一个字符串
char*strstr (const char*str1,const char*str2)//返回的是字符串2在字符串1第一次出现的位置
在str1中找str2
如果str2压根没出现,就返回空指针
几种输出结果:
模拟实现
5.strtok函数
重点是分隔符,把分隔符所分割的字符串,提取出来
写一个字符串:zpengwei@qq.com
sep:分隔符的字节集合——“@ .”,这俩就是分隔符
strtok就是找到分隔符后,把分隔符改为\0,并返回z(开头)的地址,所以他会改变被操作的字符串
根据这个函数的参数描述
我们可以得到
所给的字符串里,有几个分隔符,就会变成几个空指针
每找到一个分隔符就设为空,然后返回最开始的地址
下一次再用strtok函数,找到空指针,接着向后分割字符串
这个函数使用的条件还是挺苛刻的
字符串里有几个分隔符,就要用几次strtok函数
上面的这种写法太繁杂,因为你不知道这个字符串会有几个分隔符,总不能一个一个数吧
优化写法——比较巧妙
用的比较少,条件比较苛刻
strerror函数
当需要把错误码翻译成错误信息时可以用这个函数
错误码存放在errno.h的头文件里
直接拖到VS里打开就好
字符串函数别忘了包含头文件
因为我们这个项目里根本没有这个文件,所以一定会失败
失败原因(错误码):没有这个文件或文件夹
哪里有错误,他就会有错误码,打印出来就知道大概是什么错误了
perror函数
perror相当于封装了strerror函数,用起来更方便
随便给perror一个字符串