前言
简单记录一下一些关于字符串的函数和它们的简单的模拟实现;
1、strlen
strlen函数,用于求字符串长度的,遇到 '\0’结束统计;
既然我们要来模拟实现,我们就应该了解一下strlen函数,我们可以通过https://legacy.cplusplus.com/来了解一下它;
参数:const char * str//被统计的字符串的开始地址
返回值:size_t//返回统计到的字符,为无符号整型(这点特别注意一下);
模拟实现:
size_t my_strlen(const char*p)//采用递归的方法模拟
{
assert(p);//断言一下p指针不是空指针
if (!*p)//遇到\0不在统计,直接返回0;
return 0;
return 1 + my_strlen(p+1);
}
int main()
{
char const* p = "bit jie ye ke yyds!";
unsigned int ret1=my_strlen(p);
unsigned int ret2 = strlen(p);//与模拟的做对比
printf("%u\n", ret1);
printf("%u\n",ret2);
return 0;
}
运行结果:
2、strcpy
字符串拷贝函数,我们都知道不能给数组一次性赋值,但是通过该函数我们可以做到一次性给字符数组一次性赋值;
当然需要满足几个条件:
1、目标数组空间必须足够;
2、源头数组必须有\0;
我们来看看strcpy函数的参数:
参数:destination//目标数组;source //源头数组
返回值:返回目标数组的首元素地址;
模拟实现:
char* my_strcpy(char* dest, const char* sour)
{
assert(dest&&sour);
char* tmp = dest;//先保存一下目标数组首元素地址,防止等会找不到了
while (*tmp++ = *sour++);//即实现了赋值操作,又实现了判断停止的条件,同时也是先把\0拷贝过去了
return dest;//返回目标数组首元素地址;
}
int main()
{
char arr[30] = "***********************";
char arr1[] = "bit jiu ye ke yyds!";
char arr2[30] = "***********************";
char arr3[] = "bit jiu ye ke yyds!";
char* ret1 = my_strcpy(arr, arr1);
char* ret2 = strcpy(arr2,arr3);//对比模拟实现
puts(ret1);
puts(ret2);
return 0;
}
运行截图:
3、strcmp
字符串比较函数,我们可以用它来比较两个自负串的大小,字符串比大小不能单纯用==来进行,应为这样比较的是他们的首元素地址!!!
该函数是利用两个数组中的字符一 一比较,如果相等则往下走,直到遇到不相等的,或者直接两个字符串都比较完了则说明这两个字符串是相等的;
strcmp参数:
str1//需要比较的字符串1;str2//需要比较的字符串2;//由于两个我们只需要读取进行了,不需要改变里面内容,则我们可以加上const修饰,防止我们以后的误操作;
返回值:
若str1>str2,返回>0的值;
若str1<str2,返回<0的值;
若str1==tr2,返回=0的值;
模拟实现:
int my_strcmp(const char* p1, const char* p2)
{
assert(p1&&p2);
while (*p1 == *p2)//相等则比较下一个
{
if (!*p1)//若来到了*p1==*p2&&*p1=='\0'这个环节,说明,两个字符串比较完了都还想等,我们直接返回0就行了;
return 0;
p1++;
p2++;
}
return *p1 - *p2;//由于遇到了不相等而来到了这里,我们就直接返回其差值就行了;
}
int main()
{
const char* p1 = "bit";
const char* p2 = "yyds!";
int ret1 = my_strcmp(p1,p2);
int ret2 = strcmp(p1,p2);
printf("ret1=%d\n", ret1);
printf("ret2=%d\n",ret2);
return 0;
}
4、strcat
字符串拼接函数,将一个字符串拼接在另一个字符串末尾(从\0开始拼接);
了解strcat:
参数:destination//目标字符串;source//源头字符串;
返回值:目标字符串
strcat会将源头的\0也拼接上去,当然我们的目标字符串需要足够大;
模拟函数:
char* my_strcat(char* dest, const char* sour)
{
assert(dest&&sour);
char* cur = dest;
while (*cur)cur++;//找到目标字符串的\0
while (*cur++ = *sour++);//开始拼接
return dest;
}
int main()
{
char arr1[30] = "Hello \0*******";
char arr2[] = "bit!";
char arr3[30] = "Hello \0********";
char arr4[] = "bit!";
char* ret1 = my_strcat(arr1,arr2);
char* ret2 = strcat(arr3, arr4);
puts(ret1);
puts(ret2);
return 0;
}
运行截图:
//以上都长度不受限制的字符串(只要有\0就成!!!)
下面介绍一些长度受限的字符串:
5、strncpy
我们可以注意到strncpy与strcpy就差了一个n字母,他们的参数也是差了一个n,strncpy加了个n的感觉就是现在我们想复制几个就复制几个;
当然功能与strcpy一样;
看看strncpy函数参数:
参数:destination//目标字符串;source//源头字符串;num//需要拷贝几个;
注意:
1、如果num<=源头字符串的长度则不会追加\0,需要拷多少,就会拷贝多少,不会追加\0;
2、如果num>源头字符串的长度,则剩余的num直接追加\0填充;
模拟实现:
char* my_strncpy(char*dest,const char*sour,size_t n)
{
assert(dest&&sour);
char* tmp = dest;
while (n && (*sour))
{
*tmp++ = *sour++;
n--;
}
while (n--)//剩余n补\0
*tmp++ = '\0';
return dest;
}
int main()//模拟strncpy
{
char arr1[30] = "******************";
char arr2[] = "bit ke ji!";
char arr3[30] = "******************";
char arr4[] = "bit ke ji!";
char *ret1 = my_strncpy(arr1, arr2,strlen(arr4)+2);
char *ret2 = strncpy(arr3,arr4,strlen(arr4)+2);
puts(ret1);
puts(ret2);
return 0;
}
运行截图:
6、strncmp
与strcmp函数一样,都是用来比较字符串大小,只不过strncmp可以用来比较前num个字符串的大小;
了解strncmp函数:
参数:str1//需要比较的字符串1;str2//需要比较的字符串2;num//需要进行比较的前num个字符;
返回值:
若str1>str2,返回>0的值;
若str1<str2,返回<0的值;
若str1==tr2,返回=0的值;
模拟实现:
int my_strncmp(const char* p1, const char* p2,size_t n)
{
assert(p1&&p2);
while (n && (*p1 == *p2))
{
if (!*p1)//如果都判断到\0了都还想等,则直接返回相等
return 0;
p1++;
p2++;
n--;//只有相等n才--;
if (!n)//如果没遇到\0,但是已经判断完了要求的
return 0;
}
return *p1 - *p2;
}
int main()//模拟strncmp
{
char* p1 = "ancjka";
char* p2 = "zaancfjka";
int ret1 = my_strncmp(p1,p2,10);
int ret2 = strncmp(p1, p2, 10);
printf("ret1=%d\n", ret1);
printf("ret2=%d\n",ret2);
return 0;
}
7、strncat
与strcat一样都是拼接字符串,但是strncat是拼接前n个字符串并且主动加\0;
若需要加的个数大于源头字符串长度,就是相当于把整个源头数组拼接上去;
反之就是需要多少拼多少,最后加个\0就行;
了解strncat函数:
参数:destination//目标数组;source //源头数组;num//需要拼接的字符串个数
返回值:返回目标数组的首元素地址;
模拟实现:
char* my_strncat(char* p1, const char* p2, size_t n)
{
assert(p1&&p2);
char* cur = p1;
while (*cur)
cur++;
while (n && *p2)
{
*cur++= *p2++;
n--;
}
*cur = '\0';
return p1;
}
int main()//模拟实现strncat
{
char arr[30] = "Hello \0****************";
char arr2[] = "bitkeji!";
char arr3[30] = "Hello \0***************";
char arr4[] = "bitkeji!";
char* ret1 = my_strncat(arr, arr2, 10);
char* ret2 = strncat(arr3,arr4,10);
puts(arr);
puts(arr3);
return 0;
}
运行截图:
8、strstr
这是一个判断一个字符串是不是另一个字符串的子串;
如果是则会返回第一次出现字串的地址,若没有则返回NULL;
了解strstr:
参数:str1//字符串1;str1//字符串2(判断str2是不是str1的字串)
返回值:第一次出现字串的地址/NULL(没找到字串);
模拟实现:
const char* my_strstr(const char* dest, const char* p)
{
assert(dest&&p);
const char* cur1 = dest;
const char* cur2 = p;
const char* begin = cur1;
while (*begin)
{
cur1 = begin;
cur2 = p;
while (*cur2 && (*cur1 == *cur2))
{
cur1++;
cur2++;
}
if (!*cur2)
return begin;
begin++;
}
return NULL;
}
int main()
{
char arr[] = "Hello bit! I love bit!";
const char* p = "I ";
const char* p1 = "bitkeji";
const char* ret1 = my_strstr(arr, p);
char const* ret2 = strstr(arr, p);
if (!ret1 && !ret2)
printf("NULL\n");
else
{ puts(ret1);
puts(ret2);
}
return 0;
}
运行截图: