天天看点

字符串问题-------字符串各种基本操作的实现

接下来的几天准备备战字符串问题,因此作为备战第一天,首先应当熟悉字符串的一些基本操作,在这里 我特地将C语言的一些常见函数进行了代码的实现

#include <cstdio>
#include <time.h>
#include <string>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <algorithm>
#include <iostream>
#include <assert.h>
using namespace std;

char a[]="hello,good boy!";
char* b;
//char* c=(char*)malloc(strlen(a)*sizeof(char));
char* d=(char*)malloc((strlen(a)+1)*sizeof(char));
char* c=(char*)malloc(2*(strlen(a)+1)*sizeof(char)); //此处为什么要乘上2呢?如果不乘以2,
//那么在后面进行字符串连接的时候就会造成访问越界

//用C语言实现各种字符串操作函数

/*memcpy函数的实现*/
void mymemcpy(void* dst,const void* src,size_t num)
{
    assert(dst!=NULL&&src!=NULL);
    char* pdst=(char*)dst;
    const char* psrc=(const char*)src;
    if(dst<=src||dst>=(src+num))
    {
        while(num--)
        {
            *pdst=*psrc;
            pdst++;
            psrc++;
        }
    }
    else
    {
        pdst = pdst + num - 1;
        psrc = psrc + num - 1;
        while(num--)
        {
            *pdst--=*psrc--;
        }
    }
}

/*strcpy函数的实现*/
char* mystrcpy(char* dst,const char* src)
{
    assert(dst!=NULL&&src!=NULL);
    char* pdst=dst;
    const char*psrc=src;
    while(1)
    {
        *pdst=*psrc;
        if(*pdst=='\0') break;
        pdst++;
        psrc++;
    }
    return pdst;
}

/*strcpy函数实现第二个版本*/
char* mystrcpy0(char* dst,const char* src)
{
    assert(dst!=NULL&&src!=NULL);
    char* pdst=dst;
    const char*psrc=src;
    while ((*pdst++ = *psrc++) != '\0')
    {
        int a=1;
    };
    return pdst;
}

/*下面这个函数的实现乍看之下自护是正确的,但实际上是错误的
这样得到的字符串要么赋值不完全,要么得到的字符串不含'\0'*/
char* mystrcpy1(char* dst,const char* src)
{
    assert(dst!=NULL&&src!=NULL);
    char* pdst=dst;
    const char*psrc=src;
    while(*pdst!='\0')//while(psrc!='\0'
    {
        *pdst=*psrc;
        pdst++;
        psrc++;
    }
    return pdst;
}

int mystrcmp(const char* src1,const char* src2)
{
    assert(src1!=NULL&&src2!=NULL);
    cout<<src1<<" "<<src2<<endl;
    unsigned char* s1=(unsigned char*)src1;//此处必须使用unsigned char进行初始化,
    //这是因为如果src1为“1”,src2为“255”
    //那么按照有符号数的运算规则进行运算的时候就会出错
    unsigned char* s2=(unsigned char*)src2;
    int ret=0;
    while(!ret&&*s1) //只要当前两个字符不相等,循环就会自动结束
                     //如果两个字符串是相等的,这是就判断是否扫描到了字符串末尾的'\0'
    {
        ret=*s1-*s2;
        s1++;
        s2++;
    }
    if(ret<0) return -1;
    else if(ret>0) return 1;
    else return 0;
}

/*mystrcat无法解决内存覆盖的问题,这一点要特别注意了*/
char * mystrcat(char* dst,const char* src)
{
    assert(dst!=NULL&&src!=NULL);
    char* pdst=dst;
    const char* psrc=src;
    while(*pdst)
    {
        pdst++;
    };
    while(1)
    {
        *pdst=*psrc;
        if(*psrc=='\0') break;
        pdst++;
        psrc++;
    }
    return pdst;
}

size_t mystrlen(const char* src)
{
    assert(src!=NULL);
    size_t len=0;
    const char* psrc=src;
    while(*psrc++)
    {
        len++;
    }
    return len;
}

size_t mystrspn(const char* src1,const char* src2)
{
    size_t cnt=0;
    char* s1=(char*)src1;
    while(*s1)
    {
        char* s2=(char*)src2;
        while(*s2)
        {
            if(*s2==*s1)
            {
                break;
            }
            s2++;
        }
        if(*s2=='\0') return cnt;
        s1++;
        cnt++;
    }
    return cnt;
}

char* mystrpbrk(const char* src1,const char* src2)
{
    char* s1=(char*) src1;
    while(*s1)
    {
        char* s2=(char*) src2;
        while(*s2)
        {
            if(*s1==*s2)
            {
                return s1;
            }
            s2++;
        }
        s1++;
    }
    return NULL;
}

char* mystrtok_r(char *src,const char* delim,char** save_ptr)
{
    char* token;
    char* s=src;
    if(s==NULL) s=*save_ptr;
    size_t a=mystrspn(s,delim);//过滤掉字符串开头的分割字符
    s = s + a;
    if(*s=='/0') return NULL;//我觉得这样做是给应用过程中的while循环一个退出的条件
    token = s;
    s = mystrpbrk(token,delim);//找到下一个分割字符的位置
//    char* res=(char*)malloc((s-token+1)*sizeof(char));
//    char* temp=res;
    if(s==NULL)//处理字符串的最后一部分
    {
//        temp = token;
        *save_ptr=strchr(token,'\0');
    }
    else
    {
//        while(token!=s)
//        {
//            *temp++=*token++;
//        }
//        *temp='\0';
        *s='\0';  //此处在CodeBlocks上编译有问题
        *save_ptr=s+1;
            
    }
    return token;
}


char *mystrtok(char *s, const char *delim)
{
    static char *last;

    return mystrtok_r(s, delim, &last);
}


int main()
{
//    memcpy(c,a,strlen(a)); //此时字符串c并不等于a,这是因为a中的'\0'并没有被拷贝过来
//    mystrcpy(c,a);
//    cout<<c<<endl;
//    mystrcpy(d,a);
//    cout<<d<<endl;
//    //strcat(c,d);
//    mystrcat(c,d); //strcat函数无法解决内存重叠的问题,因此在这里要想不覆盖源字符串,可以考虑先声明源字符串,再进行拼接
//    cout<<c<<endl;
//    int tot=mystrlen(c);
//    cout<<tot<<endl;
    char * substr = "hello";
    char * str = "skl jdfhello sjdlf";
    char sentence[]="This is a sentence with 7 tokens";
    const char * str2= " ";
    char* temp0=strstr(str,substr);
    //char* temp1=mystrstr(str,substr);
    int res=mystrcmp(substr," ");
    strcmp(substr,str2);
    char* p=strtok(sentence," ");
    char* temp2=mystrtok(str,"skl");
    cout<<temp0<<" "<<endl<<temp2<<endl;
    cout<<res<<endl;
    free(d);
    free(c);
    return 0;
}