字符函数与字符串函数(下)
文章目录
- 字符函数与字符串函数(下)
- 1.strncpy的使用和模拟实现
- 1.1使用示例:
- 1.2模拟实现
- 2.strncat的使用和模拟实现
- 2.1使用示例:
- 2.2模拟实现
- 3.strncmp的使用和模拟实现
- 3.1使用示例:
- 3.2模拟实现
- 4.strstr函数
- 4.1使用示例:
- 4.2模拟实现
- 5.strtok函数
- 5.1示例;
- 6.strerror函数
- 6.1示例:
- 6.2额外补充
1.strncpy的使用和模拟实现
2.strncat的使用和模拟实现
3.strncmp的使用和模拟实现
4.strstr的使用和模拟实现
5.strset函数
6.strerror函数
在上一篇文章中学习了strcpy,strcat,strcmp,这一篇接着上篇继续介绍
1.strncpy的使用和模拟实现
strncpy实在strcpy的基础上可以限制拷贝过去字符的个数
函数声明:
char* strncpy(char* destination, char* source, size_t num);
注意事项:
如果源字符串的长度小于num个,则拷贝完源字符串后,在目标后面追加0,直到num个
1.1使用示例:
int main()
{
char s[20] = { 0 };
char a[6] = "world";
strncpy(s, a, 10);
printf("%s", s);
return 0;
}
1.2模拟实现
char* my_strncpy(char* s, char* a, size_t num)
{
char* m = s;//记录目标空间的初始位置
int count = 0;
while (count <= num)
{
*s++ = *a++;
count++;
}
printf("%s", m);
}
int main()
{
char s[20] = { 0 };
char a[15] = "hello world";
my_strncpy(s, a, 8);
return 0;
}
2.strncat的使用和模拟实现
strncat是可以指定在目标空间追加规定个字符,再追加一个’\0’.
注意事项:
如果源字符串的长度小于num的个数,只会将源字符串’\0’之前的内容追加到目标空间
函数声明:
char* strncat(char* destination, char* source, size_t num);
2.1使用示例:
int main()
{
char s[20] = "hello ";
char a[10] = "world";
strncat(s, a, 3);
printf("%s", s);
return 0;
}
2.2模拟实现
char* my_strncat(char* s, char* a, size_t num)
{
char* m = s;
int count = 1;
while (*s)
{
s++;
}
while(count<=num)
{
*s++ = *a++;
count++;
}
printf("%s", m);
}
int main()
{
char s[20] = "hello ";
char a[10] = "world";
my_strncat(s, a, 3);
return 0;
}
3.strncmp的使用和模拟实现
比较str1和str2的前num个字符,如果相等,就继续向后比较,最多比较num个字符,如果提前找到不同,就提前结束,大的所在字符大于零一个字符;如果num个字符都相等,就返回0;
函数声明:
int strncmp(const char* str1,const char*str2,size_t num);
3.1使用示例:
int main()
{
char s[10] = "abcdef";
char a[10] = "abcdeg";
int ret = strncmp(s, a, 5);
printf("%d", ret);
return 0;
}
3.2模拟实现
char* my_strncmp(char* s, char* a, size_t num)
{
int count = 0;
while (*s == *a)//注意这里如果是一个等号的话,就相当于把*a的值赋给了*s
{
s++;
a++;
count++;
if (*s == '\0' || count==num)
return 0;
}
return *s - *a;
}
int main()
{
char s[10] = "abcdef";
char a[10] = "abcdeg";
int ret=my_strncmp(s, a, 5);
printf("%d", ret);
return 0;
}
4.strstr函数
函数声明:
char* strstr(const char*str1,const char*str2);
在上边的图片中很容易知道该函数的返回值,同时,在strstr函数中,字符串的匹配不包含’\0’,以’\0’作为结束标志。
4.1使用示例:
int main()
{
char str[30] = "This is a simple string";
char* pch = 0;//创建一个指针接受strstr的返回值
pch = strstr(str, "simple");
strncpy(pch, "sample", 6);
printf("%s",str);
return 0;
}
到这一点代码都还是很容易理解的
4.2模拟实现
分析:
很明显,看图首先我们先创建了一个指针变量m来记录str1的初始位置,方便后边找到他和使用他
然后我们想找到str1中是否含有str2,那就要一个一个字符进行对比,如果是str1=‘abcdef’,str2=‘bcde’,那很容易找到
复杂一点的情况就是出现如图所示的情况,当我们对比一半的时候发现出现不一样了
那怎末解决呢?
确定一个对比的起点,从这个起点开始一一比较,不符合,向后走,再以后一个字符作为比较的起点
因此我们又创建了两个指针变量,e1 和e2,首先以e1为起点,从e2开始一点点比较,出现不符合时,e1向后移一位,作为起点,e2重新开始与以e1+1为起点的字符串开始一一比较
char* my_strstr(const char* a, const char* b)
{
char* m = a;
char* e1;//记录a开始比较的位置
char* e2;//记录b开机比较的位置
if (!*b)
return a;//排除掉b是空指针的情况,如果是空指针返回a
while (*m)
{
e1 = m;//一个一个位置开始比较
e2 = b;
while (*e1 && *e2 && *e1 == *e2)//确保*e1和*e2都不为空
{
e1++;
e2++;
}
if (*e2 == '\0')//说明找到了str2最后的位置,此时的m的位置就是str2首次出现的位置
return m;
m++;//当出现不同,并且也没有走到str2的最后时,说明此时的起点不对,向后移一位在开始一个一个比较
}
return (NULL);//当m一直向后走寻找新的起点,一直都没找到时返回空指针
}
int main()
{
char a[20] = "aaabcdef";
char b[10] = "aabcdd";
char* pch=my_strstr(a, b);
if (pch != (NULL))
printf("有");
else
printf("无");
return 0;
}
上边给的代码例子就是当我们以第二个a为起点的时候,找到最后发现不同的情况
5.strtok函数
函数声明;
char*strtok(char* str,const char* sep);
上面图片的解释可能不太好理解,再来解析一下这个函数的用法
sep这个参数它指向了一个字符串,定义了一个用作分隔符的字符集合
str指定一个字符串,它包含了0个或多个sep中一个或多个分隔符分割的标志
strtok找到str中的下一个标记,并将其用’\0\结尾,返回一个指向这个标记的指针
需要注意的是,strtok函数会改变str字符串的内容,所以被分割的字符串通常是临时拷贝的,且可以修改的
strtok的第一个参数不是空指针时,函数将找到str中的第一个标记,并保存他在字符串中的位置
strtokd的第一个参数是空指针时,函数在同一字符串被保存的位置开始,找下一个标记
如果不再存在更多的标记,返回空指针
5.1示例;
int main()
{
char s[100] = "123.4.56";
char* sep = ".";
char* str = NULL;
for (str = strtok(s, sep); str != NULL; str = strtok(NULL, sep))//初始化先找到第一个标记,调整部分是第一个参数是空指针,就在标记的地方继续找下一个标记
//条件是str不是空指针,因为如果找不到下一个标记,就会返回空指针
{
printf("%s\n", str);//输出123
//4
//56
}
return 0;
}
在看一个,理解一下
int main()
{
char s[100] = "_this,a simple thing";
char* pch;
printf("Splitting string\"%s\"into tokens\n", s);//先把字符串s 加进来输出
pch = strtok(s, "_, ");//先找到第一个标记,这里设置的间隔标记有三个分别是- ,和空格注意'\0'不能做分隔符,读到'\0'字符串就结束了
while (pch != NULL)
{
printf("%s\n", pch);//输出this a sample thing
pch = strtok(NULL, "_, ");//从上一次标记开始向后找到下一个标记
}
return 0;
}
理解完上边的例子,下边这个就很容易理解了
int main()
{
char s[20] = "hello,wor\0ld";
char* pch;
for (pch = strtok(s, ",\0"); pch != NULL; pch = strtok(NULL, ",\0"))
{
printf("%s", pch);//输出hellowor
}
return 0;
}
6.strerror函数
char* strerror(int errnum);
strerror函数可以把参数部分错误码对应的错误信息的字符串地址返回来
注意:
1.不同的系统和c语言标准库都规定了一些错误码,一般是放在<errno.h>这个头文件
2.C语言使用一个全局变量errno来记录程序的当前错误,程序启动时errno为0;表示没有错误
3.当使用标准库函数发生错误时,就会将对应的错误码放在errno中,strerror函数就可以把错误对应的错误信息字符串的地址返回
6.1示例:
#include<errno.h>
int main()
{
//printf(strerror(errno));
int i = 0;
for (i = 0; i <= 10; i++)
{
printf("%s\n", strerror(i));//展示出可能出现的错误的原因
}
return 0;
}
写一个代码看看他是怎么使用的
int main()
{
FILE* pFile;//声明了一个指向FILE类型的指针pFile,用于文件操作
pFile = fopen("unexit.ent", "r");//使用fopen函数尝试以只读模式('r')打开名为unexit.ent的文件,并返回文件的指针赋值给pFile;
if (pFile == NULL)//判断文件是否为空,若为空打开失败,输出失败的原因
{
printf("error opening file unexit.ent:%s\n", strerror(errno));//这个失败的原因是我根本就没有这个文件
}
return 0;
}
6.2额外补充
也可以了解一下perror函数
他相当于一次把打印和调用strerror函数完成了,将直接把错误信息打印出来,并且在他打印完参数后,会打印一个冒号和空格再打印错误信息
int main()
{
FILE* pFile;
pFile = fopen("unexit.ent", "r");
if (pFile == NULL)
{
perror("error opening file unexit.ent");//这个失败的原因是我根本就没有这个文件
}
return 0;
}
作者有话说:作者只是一直刚学的小白,以上理解均是作者学习完后对知识的理解,如有错误和不当,感谢指出,如感到有帮助,请留下一个👍