C语言字符串函数归纳。

首先需要知道在c语言中本身并没有字符串类型,字符串通常放在常量字符串中或者字符数组中

1.实现strlen

首先strlen函数的作用是求字符串长度的。'\0’是它的结束标志,strlen函数返回的是在字符串中‘\0’前面出现的字符个数,strlen函数的返回值为size_t,是无符号的,它的实现有三种方式。

第一种用指针和计数器的方式。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int my_strlen(char* str)
{
  int count=0;
  while(*str)
  {
    str++;
    count++;
  }
  return count;
}
int main()
{
  char str[]="asdvssdvsdv";
  printf("%d\n",my_strlen(str));
  return 0;
}

这是最简单也是很容易理解的一种方式。

第二种递归的方式。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int my_strlen(char* str)
{
  if(*str=='\0')
    return 0;
  else
    return 1+my_strlen(str+1);
}
int main()
{
  char str[]="asdvssdvsdv";
  printf("%d\n",my_strlen(str));
  return 0;
}

第三种是采用指针和指针的方式。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int my_strlen(char* str)
{
  char* p=str;
  while(*p!='\0')
      p++;
  return p-str;
}
int main()
{
  char str[]="asdvssdvsdv";
  printf("%d\n",my_strlen(str));
  return 0;
}

2实现strcpy

首先应该知道它的作用是复制,char* strcpy(char* destination,const char* source)目标空间应该足够大,以确保能存放源字符串,源字符串必须以‘\0’结束,会将源字符串的‘\0’拷贝到目标空间。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<assert.h>
#include<algorithm>
using namespace std;
char* my_strcpy(char* dest,char* src)
{
  char* ret=dest;
  assert(dest!=NULL);
  assert(src!=NULL);
  while((*dest++==*src++)!='\0')
  {;}
  return ret;
}
int main()
{
  char str1[]="hello";
  char str2[]="world";
  printf("%s\n",my_strcpy(str1,str2));
  return 0;
}

assert是判断指针有效性的函数。是把dest复制到原函数上面。循环写成while(*dest++=*src++)明显是错误的,不知什么时候结束。循环写成while(*src!='\0'){*dest++=*src++;}也是错误的,循环体结束后,dst末尾并没有加上‘\0’.
2.实现strcat

该函数的作用是拼接函数,stract(str1,strr2),str2是源,str1是目标函数,是把源拼接在目标函数上,目标函数必须足够大,能容纳下源字符串的内容。

#include<iostream>
#include<algorithm>
#include<assert.h>
#include<cstdio>
using namespace std;
char *my_strcat(char* dest,char *src)
{
  char* ret=dest;
  assert(dest!=NULL);
  assert(src!=NULL);
  while(*dest!='\0')
  {
    dest++;
  }
  while((*dest++=*src++))
  {
    ;
  }
  return ret;
}
int main()
{
  char str1[]="hello";
  char str2[]="world";
  my_strcat(str1,str2);
  printf("%s\n",my_strcat(str1,str2));
  return 0;
}


3.实现strcmp

该函数的作用是比较另个字符串是否完全相同。此处用返回相关数值表示。返回0表示完全相同,返回1表示不相同。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<assert.h>
using namespace std;
int my_strcmp(char* src,char* dst)
 {
  assert(src!=NULL);
  assert(dst!=NULL);
   while(*src==*dst)
   {
       if(*src=='\0')
        return 0;
     ++src;
     ++dst;
   }
   if(*src>*dst)
      return 1;
   else
     return -1;
 }
int main()
{
  char str1[]="hello";
  char str2[]="hellv";
  my_strcmp(str1,str2);
  cout<<my_strcmp(str1,str2)<<endl;
  return 0;
}


4.实现strchr

strchr 原型为extern char *strchr(const char *s,char c),可以查找字符串s中首次出现字符c的位置。此函数并不常用。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<assert.h>
using namespace std;
char* my_strchr(char* str,char c)
{
  assert(str!=NULL);
  while(*str!='\0')
  {
    if(*str==(char)c)
    {
      return (char*)str;
    }
    str++;
  }
return NULL;
}
int main()
{
  char str[]="abcdefg";
  char *p;
  p=my_strchr(str,'f');
  if(p==NULL)
  {
    cout<<"Not Find"<<endl;
  }
  else
  {
    cout<<"Find"<<endl;
    cout<<p<<endl;
  }
  return 0;
}


5.实现strstr

strstr函数的作用是找字符串的子串

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<assert.h>
using namespace std;
char* my_strstr(char* str1,char* str2)
{
  assert(str1!=NULL);
  assert(str2!=NULL);
  char* start=(char*)str1;
  char* substart=(char*)str2;
  char* cp=(char*)str1;
  while(*cp)
  {
    start=cp;
    while(*start!='\0'&&*substart!='\0'&&*start==*substart)
    {
      start++;
      substart++;
    }
    if(*substart=='\0')
      return cp;
    substart=(char*)str2;
    cp++;
  }
  return NULL;
}
int main()
{
  char str1[]="abbbcdefg";
  char str2[]="bbcd";
  cout<<my_strstr(str1,str2)<<endl;  
  return 0;
}

首先,根据strstr函数的实现方法得知函数需要传进去的参数是两个字符串,而且这两个字符串都是不可更改的,这样,我们可以利用const来修饰;而且函数返回的也是一个字符串,那么返回值类型也可以确定,这样,我们可以写出这样一个函数的定义:char* my_strstr(const char* dest,const char* src){}。其中,dest指向的是目标字符串,也就是你需要比较的字符串,src指向的是源字符串,也就是用来被比较的字符串。找不到就可以返回一个空指针。

实现的思路也是比较简单的,你可以建立两个指针,通过遍历的方式逐个访问字符串,并对这两个指针一一比较。

举例说明:给上俩个字符串:

str1:abcdefg

str2:bcd

建立两个指针:char *start=str1; char *substart=str2;

此时,start指向字符a,而substart指向字符b,对start和substart两个指针解引用并进行比较,判断是否相等,即*start=*substart;若是两个相等,则两个指针都向后移动一位,再解引用进行判断;若是两个不相等,那么start向后移动一位,substart则将会重新指向str2的起始位置,两个再次进行比较。重复这个过程,直到两个字符串其中一个或者是两个都遇到‘\0’,遍历结束。那么在这里你就可以采用循环的方法来做;循环的判断条件就是(start!='\0' && substart!='\0' && *start==*substart)。

如果到这里你觉得这个函数就算实现成功的话,那你可就掉到坑里去了。我再举个例子吧:

str1:abbbcdefg

str2:bbcd

这里你继续采用上面的方式做,你会得到不一样的结果。

指针判断,当start指向str1中的第一个b时,substart指向str2中的第一个b,两个相等,再往后面遍历,当start指向第三个b的时候,substart指向c,两个不相等,那么此时substart会返回并指向str2中的第一个b。

注意,此时start指向的还是str1中的第三个b,start并没有发生移动,再采用如上的方式比较,从str1的第三个b开始,你再也找不到与str2相同的,那么函数会返回一个 空,可是显然第一个字符串中包含你需要的查找的字符串。这样,我们就需要通过某种方法来解决这个问题。

解决方法其实也是比较简单的:当两个字符串比较的结果不相等时,我们知道substart,就是指向第二个字符串的指针是返回到str2这个字符串的起始位置的,而start这个指针并没有发生任何的变动。再次比较也只能从这个位置继续向后比较,那么中间肯定就会有一些字符是没有办法比较的。所以,当两个字符比较不相等时,start这个指针也需要向前返回,不过它回到的不是起始位置了,而是起始位置的下一个位置,这样就可以避免重复而无用的比较。所以,我们需要在创建一个指针cp用来保存起始位置,并让start返回到起始位置的下一个位置。(此处为从别人博客摘抄的,感觉写的特比妙)
6.实现memcpy

mecmpy是内存的拷贝函数

这个函数的原型是 void* mecmpy(void* destination,const void* source,size_t num);函数mecmpy从source 的位置开始向后复制num个字节的数据到destination的内存位置。注意这个函数在遇到'\0'是不会停下来的。如果source和destination有任何的重叠,复制的结果都是未定义的。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
void* my_memcpy(void* dst,void* src,size_t count)
{
  void* ret=dst;
  while(count--)#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
void* my_memcpy(void* dst,void* src,size_t count)
{
  void* ret=dst;
  while(count--)
  {
    *(char* )dst=*(char* )src;
    dst=(char*)dst+1;
    src=(char*)src+1;
  }
  return ret;
}
int main()
{
  float arr1[]={1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0};
  float arr2[10];
  int len=sizeof(arr1)/sizeof(arr1[0]);
  my_memcpy(arr2,arr1,len);
  return 0;
}

  {
    *(char* )dst=*(char* )src;
    dst=(char*)dst+1;
    src=(char*)src+1;
  }
  return ret;
}
int main()
{
  float arr1[]={1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0};
  float arr2[10];
  int len=sizeof(arr1)/sizeof(arr1[0]);
  my_memcpy(arr2,arr1,len);
  return 0;
}

https://blog.csdn.net/Hanani_Jia/article/details/78992428这篇文章把mecmpy写得特别好。
7.实现memmove

此函数和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的,如果源空间和目标空间出现重叠,就得使用memmove函数处理

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
void* memove(void* dst,const void* src,size_t count)
{
  void* ret=dst;
  if(dst<=src||(char*)dst>=((char*)src+count))
  {
    while(count--)
    {
      *(char *)dst=*(char *)src;
      dst=(char*)dst+1;
      src=(char*)src+1;
    }
  }
  else
  {
    dst=(char*)dst+count-1;
    src=(char*)src+count-1;
    while(count--)
    {
      *(char*)dst=*(char*)src;
      dst=(char*)dst-1;
      src=(char*)src-1;
    }
  }
  return ret;
}
int main()
{
  char str1[]="hello";
  char str2[]="world";
  int len=strlen(str1);
  memmove(str1,str2,len);
  cout<<memove(str1,str2,len)<<endl;
  return 0;
}

复制的是一个内存。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值