字符串函数(解析和运用)

简单的字符串函数分类

复制:

strcpy strncpy

串联:

strcat strncat

比较:

strcmp

查找:

strstr

求字符串长度:

strlen

以上字符串函数均来源于库函数<string.h>,使用时需引用该头文件

使用方法及源码分析

注:以下使用的字符指针均不为空指针

Copying:

作用:

将源字符串中第一个'\0'和它之前的所有字符放到目标字符串中,相当于复制粘贴,但会将目标字符串的字符覆盖掉。

从定义看出,strcpy函数调用时需要两个指针类型的参数,

其中一个destination(下文简写为dst),指向目标字符串的首元素地址;

另一个为不可变更的source(下文简写为src),即源字符串的首元素地址;

两个参数均为指针变量,传址以节省内存。

strcpy函数的返回值类型为字符指针变量,指向目标字符串的首元素地址,用output标记。

    //我们不希望src的值在使用的过程中被改变,所以定义时使用const
char * my_strcpy(char * dst,const char * src)
{
    char* output = *dst;    //put记录目标空间的首元素地址
    while(*src)         //源字符串的单个字符不为‘\0’时循环继续,即源字符串还没结束
    {
        *dst = *src;    //源字符串的单个字符对目标空间的单个空字符一一赋值
        src++;
        dst++;
    }
    *dst = *src;        //最后要把结束符'\0'复制过去
//while循环精简版:>    while(*dst++ = *src++);    <---别忘了末尾的‘ ; ’
//精简版括号内的条件执行顺序是:先赋值  ——令*dst = *src;
//                         再++   ——让src指针和dst指针指向下一个待赋值的字符的地址
//                         最后判断——由于括号内是赋值语句,因此循环结束的条件是看*src的值
//                                                          注意15行的src是未自增前的src
    return output;
} 
int main()
{
    char arr1[20] = {0};
    char arr2[20] = "Have a good day";
    my_strcpy(arr1,arr2);
    printf("%s\n",arr1);
    return 0;
}

Ps:源字符串必须以'\0'结束,,,

复制时会将'\0'拷贝到目标空间,,,

必须确保目标空间足够大来存放源字符串,,,

strncpy与strcpy十分相似,不同在于strncpy胖了“n”点,即str(n)cpy

strncpy的定义也不同一点,调用三个参数,前两个参数与strcpy相同,第三个参数表示要从源字符串中复制 num 个字节的内容到目标字符串中。注意num的”单位“为1个字节。

num的类型为sisz_t 即unsigned型

char * my_strncpy (char * dst,const char * src,size_t num)
{
    char * output = dst;
    while(num)
    {
        *dst = *src;
        dst++;
        src++;
        num--;
    }
//while循环精简版:>    while(num &&  (*dst++ = *src++)  )
//                        num--;

    if(num)                //判断num的长度是否超过源字符串长度
    {
        while(num--)        
        {
            *dst = '\0';    //若超过了,则将多余字节的内存全部赋值为'\0'
            *dst++;
        }
//while循环精简版:>    while(num--)
//                        *dst++ = '\0';
    }
    return output;
}
int main()
{
    char arr1[20] = {0};
    char arr2[] = "Have a good day"; 
    my_strncpy(arr1,arr2,5);    //num的值自己赋,可以使用sizeof( )进行赋值
    printf("%s\n",arr1);
}

Ps:如果源字符串的长度小于num的长度,那么会将多余的内存全部赋值为'\0'


Concatenation:

作用:

将目标字符串和源字符串连接起来,类似“A”+“B” == “AB”

由定义可知使用strcat函数需要传两个字符指针变量作为参数,一个是目标字符串的地址dst,另一个是源字符串的地址src,strcat函数的返回值类型为字符指针类型

char* my_strcat(char * dst,const char* src)  
{
    char* output = dst;
    while (*dst)        //*dst != '\0'时循环继续,即找到目标函数的结束符
        dst++;
//上述循环等价于:>        while(*dst++) ;   
//                        dst--;      用以作为条件去判断的是 *dst ,
//                                    而实际上dst的值却是dst+1,因此要dst要减一指向的才是'\0'的地址
    while(*src)             //再在结束符处串联要追加的源字符串
    {
        *dst = *src;
        dst++;
        src++;
    }
    *dst = '\0';
//第二个while循环精简版:>    while (*dst++ = *src++) ;
    return output;
}
char* my_strncat(char* dst, const char* src, size_t num)
{
    char* output = dst;
    while (*dst)
        dst++;           //找到目标字符串中'\0'地址
//上述循环等价于:>        while(*dst++) ;   
//                        dst--;      用以作为条件去判断的是 *dst,
//                                    而实际上dst的值却是dst+1,因此要dst要减一指向的才是'\0'的地址
    while (num)
    {
        if (*src)
        {
            *dst = *src;
            dst++;
            src++;
        }
        else
            {
            *dst = '\0';
            return output;    //当num的值大于源字符串长度时,会将源字符串后面 一个 字节的内存赋值为'\0'
            }
        num--;
    }
//while精简版:>     while(num--)
//                    if( ! (*dst++ = *src++) )           
//                         return output;
    *dst = '\0';        //当num的值小于源字符串的长度时,为目标字符串赋结束符
    return output;
}

Ps:

目标空间必须足够大,,,

源字符串必须以'\0'结尾,,,


Comparison:

作用:

比较两个字符串的首个字符的ASCII码,若相同,则继续往后比较直至一方或双方遇到'\0'

若比到最后仍相等,则输出 0

若前者大于后者的ASCII码,则输出一个大于0的数

若前者小于后者的ASCII码,则输出一个小于0的数

从定义来看,strcmp函数的使用需要传两个参数——两个待比较字符串的首元素地址,因此用char * str1 和char * str2 两个字符型指针变量来指向两个待比较字符串的首元素地址,又因为我们两个待比较的字符串不能随意变更,即常量字符串不能改变,因此对两个变量加上const修饰。由定义可知,strcmp函数的返回值类型是整型。

int my_strcmp(const char * str1 ,const char * str2)
{
    int ret = 0;    //用来存储 str1 和 str2 比较的字符的ASCII码的差值
    while(*str1 && *str2)        //未遇到 '\0' 时循环继续,即此前的字符都相同,比较继续
    {
        ret = *str1 - *str2;    //以ret作为返回值,用以区分字符串大小
        str1++;
        str2++;
    }
//while简写:   while (      (   ! (ret = *str1 - *str2)  )     &&   *str2  )
//                str1++, str2++;
//  while()   括号中 ret = *str1 - *str2 在赋值的同时作为条件存在,一举两得
    return ret;
}

和strcmp函数相比,strncmp函数调用时需要传入第三个参数size_t 即unsigned类型的num。这个num代表的是 num个字节


Searching:

char *strstr( const char *str1, const char *str2 );

作用:

在源字符串str1中查找是否存在目标字符串str2,若存在,返回str2在str1中第一次出现的地址;若不存在,则返回空指针(NULL)

char* my_strstr(const char* str1, const char* str2)                        //查找子字符串
{
    char* now = (char*)str1;        //now用来记录当前这一次查找是从第几个字符开始的
    char* s1 = (char*)str1;
    char* s2 = (char*)str2;
//不直接使用str1和str2是为了方便记录now的位置
    if (*str2 == '\0')        //当要查找的字符串是空字符串时,直接返回空指针
        return NULL;

    while (*now!='\0')        //从str1的首字符开始,以逐个字符为头和str2进行对比,
    {                          //直到遇到str1的结束符'\0'
        s1 = now;
        s2 = (char*)str2;
        while (*s2 != '\0' && *s1 == *s2)    //对比
        {
            s1++;
            s2++;
        }
        if (*s2 == '\0')        当查找完成后,返回str2在str1中首次出现的地址
            return (char*)now;
        now++;
    }
    return NULL;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值