文章目录
书接上文,上次简单总结了strlen、strcmp、strcpy、strcat、strtok这几个函数的使用和模拟。这次总结以下strstr、strn开头的几个函数、atoi等字符串操作函数和模拟实现。
一、strstr的使用和模拟实现
1. strstr的使用
strstr函数的作用是查找一个字符串中是否包含另一个字符串,及一个字符串是否是另一个字符串的子串。倘若是,则返回原字符串中包含字符串的首元素地址,否则返回空指针。可以看到strstr的函数声明是这样的:
函数的使用效果如图所示:
当函数没有找到相同字符串的时候,就会返回空指针
2. strstr模拟实现
知道了该函数的效果,参数和返回类型后,我们可以来模拟一下strstr函数
char* strstr(const char* str1, const char* str2)
{
assert(str1 && str2);//避免参数传了空指针,NULL的值为0;
const char* tmp1 = str1;
const char* tmp2 = str2;
while(*str1)
{
while(*str1 != *str2)//在str1中找第一个字符与str2首字符相同的;
{
str1++;
tmp1++;//用tmp1来记住首元素地址;
if(*str1 == '\0')//当str指向'\0'的时候,说明找不到了
return NULL;
}
while(*str1 == *str2)//找到首字符相同的之后,判断剩下的等不等;
{
str1++;
str2++;
if(*str2 == '\0')
{
return (char*)tmp1;//const char*转换为char*,免得报警告
}
}//如果中间出现不相同的字符,则跳出此循环,重置str1和str2;
str1 = tmp1;
str2 = tmp2;
str1++;//找下一个字符;
}
return NULL;//当str指向最后的一个字符的时候,说明找不到了
}
根据逻辑初步的模拟就完成了,可以看到,效果和库函数相差无几:
但是我们可以发现,代码中有很多冗余,如外层循环的判断和内层循环的判断逻辑是一致的,因此我们可以稍作修改
char* strstr(const char* str1, const char* str2)
{
assert(str1 && str2);//避免参数传了空指针,NULL的值为0;
const char* p1 = str1;
const char* p2 = str2;
for(; *p2; p1++,p2++)
{
for(; *p1 != *p2; p1++,str1++)
{
p2 = str2;//第二次进来是,把p2给初始化到首字符的位置;
if(*p1 == '\0')
return NULL;
}
}
return (char*)str1;
}
这一次将两次对于str1的判断整合到一块去了,把调整部分整合进了for循环,看着就紧凑了许多。并且全程没有动str1和str2,保证了其不会被修改。
二、strncmp的使用和模拟实现
1. strncmp的使用
长话短说,strncmp和strcmp作用一样,多出来的n也是传参时的一个参数,为比较的字节个数,其形式如下:
其它的东西在上一篇已经提到过,在此不再赘述。
2. strncmp的模拟实现
代码如下(示例):
int strncmp(const char* str1, const char* str2, int count)
{
for(;count--;str1++,str2++)
{
if((*str1 != *str2) || (*str1 == 0) || (*str2 == 0))
return *str1 - *str2;
}
return 0;
}
核心思想就是这么简洁易懂,另一个版本也是一样
int strncmp(const char* str1, const char* str2, int count)
{
while(count--)
{
for (; (*str1 == *str2) && (*str1) && (*str2); str1++, str2++);
return *str1 - *str2;
}
return 0;
}
本质上是一个意思。至于VS版本的-1,0,1的返回值在此就省略了。
三、strncpy的使用和模拟实现
1. strncpy的使用
同上,略过使用说明,加了一个n限制拷贝的字符数,其他使用事宜见上一篇。
2. strncpy的模拟实现
也很简单,甚至比strcpy还简单,在此直接给出
char* strncpy(chat* str1,const char* str2,int count)
{
char* p = str1;
while(count--)
*str1++ = *str2++;
return p;
}
当然能不越界还是别越界的好。
四、strncat的使用和模拟实现
1. strncat的使用
同上,略过使用说明,加了一个n限制拷贝的字符数,其他使用事宜见上一篇。
2. strncat的模拟实现
char* strncat(chat* str1,const char* str2,int count)
{
char* p = str1;
for(; *str1; str1++);//找到str1的结束位置;
for(; count--; str1++, str2++)
{
*str1 = *str2;
}
return p;//返回str1的起始位置;
}
总结
strn系列的函数解决了str中很容易出现的越界问题,由编程者自己来决定要使用多少个字符,可以有效的预防bug的产生,不过字符串操作函数终归只能操作字符串,涉及到整型方面的内容,我们还会使用到memory系列函数,而这就是下次的内容了。
日常记录总敲代码行数:3707