字符串函数及字符串函数的实现(1)

C语言中关于字符和字符串的操作是非常多的,操作字符和字符串往往就要用到字符串相关的函数。因此在这里我们就先来了解下函数库中的字符串函数,并且自己实现字符串函数。
strlen

size_t strlen ( const char * str );

字符串是以‘\0’作为结束标志,strlen函数是用于求字符串的字符长度(不包括‘\0’),它的返回值是字符串‘\0’前字符的个数。

strlen的模拟实现(my_strlen)

size_t my_strlen(const char* str){                                                                                               
    assert(str != NULL);
    size_t count = 0;
    while(*str++ != '\0'){
        count++;
    }
    return count;
}

strcpy

char* strcpy(char * destination, const char * source );

字符串拷贝需要两个字符串,一个为源字符串,一个为目标字符串,字符串拷贝只进行字符串拷贝,并且会将字符串的结束符也给拷贝进去,因此字符串拷贝时会有以下要点:

  • 源字符必须是以‘\0’结束。
  • 目标空间必须足够的大,可以容纳源字符。
  • 源字符会将‘\0’拷贝进目标空间。
  • 目标空间必须可见

举个实例:

char str1[100] = "abcdef";
char str2[100] = "ABCD";
strcpy(str1,str2);
printf("%s\n",str1;
//此时数组输出的是什么

如上例,按照正常来说,目标空间里应该存放的是”ABCD\0ef”,但最终输出的结果却是”ABCD”,这是为神魔呢。解决这个问题就要了解上面所说的字符串拷贝的一些要点了,字符串拷贝时将‘\0’也一同拷贝,从而将原字符串隔断了,因此就只显示了str2。
strcpy的实现(my_strcpy):

char* my_strcpy(char* dst,const char* src){
    assert((dst != NULL)&&(src != NULL));
    char* ret = dst;
    while((*dst++ = *src++) != '\0';
    retrun ret;
}

通过上面的实例我们可以看出,strcpy只能讲一个完整的字符串拷贝进另一字符串中,而且还会覆盖该字符串(这就有一种耍流氓的感觉),因此为了解决这一问题,我们就有了strncpy,它可以将源字符串的一部分复制到目标字符串中。

char *strncpy( char *strDest, const char *strSource, size_t count );

my_strncpy:

char* my_strncpy(char* dst,const char* src,size_t num){
    assert((dst != NULL)&&(src != NULL));
    char* ret = dst;
    while(num-- && (*dst++ = *src++)!='\0');
    return ret;
}  

strcpy和strncpy的思路是相似的,但是strcpy在拷贝字符串的时候会将字符串的结束符‘\0’也拷贝到目标空间中,而strncpy不会将‘\0’拷贝进去(除了最后一个参数是sizeof(src)),因此可以说strcpy是字符串拷贝,而strncpy是字符拷贝。
strcat

char *strcat( char *strDestination, const char *strSource );

strcat是将源字符串拷贝到目标字符串之后,在拷贝时源字符串会覆盖掉目标字符串最后的‘\0’。要实现strcat需要具有以下几个要点:

  • 源字符串必须以‘\0’结尾
  • 目标字符串空间必须足够的大,要保证可以放下源字符串的所有内容
  • 目标空间必须可以修改

strcat的模拟实现:

char* my_strcat(char* dst,const char* src){
    assert((dst != NULL)&&(src != NULL));
    while(*dst != '\0'){
        dst++;
    }
    while((*dst++ = *src++) != '\0');
    return dst;
}

strcat还有一个需要注意的问题:当dst为数组,src为指针时,如下例:

int main(void)
{
    char dst[6] = "Hello";
    char *src = "World";

    strcat(dest, src);
    printf("%s\n", dest);

    return 0;
}

其输出结果为:HelloWorld,按理来说dst应该没有足够的空间来存储src,但却可以正常编译,且结果正确,很明显,这属于数组越界的问题,在C语言中,c不检查也不提示,所以这里的拷贝用到了dst[6]后面紧挨着的几个存储单元,因此如果dst和src反过来就是不可以的了。
strcat只是将src整体拷贝在dst后面(覆盖了‘\0’),但如果只想将src一部分拷贝到dst后面呢?这就引用了strncat。

char *strncat( char *strDest, const char *strSource, size_t count );

strncat的模拟实现:

char* my_strncat(char* dst, const char* src, size_t num){
    assert((dst != NULL)&&(src != NULL));
    while(*dst != '\0'){
        dst++;
    }
    while(num--){
        *dst++ = *src++;
    }
    return dst;
}

strcmp

int strcmp( const char *string1, const char *string2 );

strcmp其主要功能是比较两个字符串,它有以下要点:

  • string1大于string2,则返回大于0的数,我们一般返回1。
  • string1等于string2,返回0。
  • string1小于string2,返回小于0的数,我们一般返回-1。
    strcmp两个字符串比较的是其每个字符的ASCII值,比较是每个字符之间进行比较,依次往后比较,只要有大于就返回1,有小于就返回-1,只有当整个字符串比较结束时,才能判断两字符串是否相等。
    strcmp模拟实现:
int my_strcmp(char* str1,const char* str2){
    assert((str1 != NULL)&&(str2 != NULL));
    while((*str1 != '\0')||(*str2 != '\0')){
    if(*str1 > *str2){
        return 1;
    }
    if(*str1 < *str2){
        return -1;
    }
    str1++;
    str2++;
    }
    return 0;
}

strcmp只满足与两个完整的字符串相比较,因此当我们需要比较两个字符串的前n个字符的时候,我们就要引用strncmp函数。

int strncmp( const char *string1, const char *string2, size_t count );

strncmp的模拟实现:

int my_strncmp(const char* str1, const char* str2, size_t num){
    assert((str1 != NULL)&&(str2 != NULL));
    while(num--){
        if(*str1 > *str2){
            return 1;
        }   
        if(*str1 < *str2){
            return -1; 
        }   
        str1++;
        str2++;                                                                                                                                     
    }   
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值