string.h相关函数介绍

目录

一、函数的组成和介绍

       1.strlen

        2.strcpy

        3.strcat

        4.strcmp

        5.strncpy

        6.strncat

        7.strncmp

        8.strstr

        9.strtok

        10.strerror

        11.字符分类函数

        12.字符转换函数

        13.memcpy

        14.memmove

        15.memcmp

二、函数的实现

1.strlen

2.strcpy

3.strcat

4.strstr

5.strcmp

6.memcpy

7.memmove


一、函数的组成和介绍

       1.strlen

              size_t     strlen ( const char * str );

            函数组成

                         输入const  char* str:  指向要求长度的字符串元素首地址。

                         返回值szie_t(无符号整型):  是传入指针指向的字符串的长度。

                   介绍

                         返回str指向的字符串的长度。


        2.strcpy

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

             函数组成

                         输入:1.char* destination:  需要拷贝的目标地址。

                                    2.const char* source:  被拷贝的源地址。

                         返回值char*:  指向要拷贝元素的目标数组的地址(destination)。

                   介绍

                         拷贝source指向的字符串到destination指向的地址。                    


        3.strcat

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

            函数组成

                         输入:1.char* destination:  需要拷贝的目标地址。

                                    2.const char* source:  被附加的源地址。

                         返回值char*:  指向要附加元素的目标数组的地址(destination)。

                介绍

                       附加source到destination的后方,覆盖最后的'\0',并在附加结束后在末尾添'\0'。


        4.strcmp

               int   strcmp (const char *    str1, const char *    str2 );

            函数组成    

                         输入:1.const char* str1:  指向要判断的第一个字符串的首元素地址。

                                    2.const char* str2:  指向要判断的第二个字符串的首元素地址。

                         返回值int : 1.str1 < str2,返回<0的数值(Visual Studio 中为  -1)

                                              2.str1 = str2,返回0

                                              3.str1 > str2,返回>0的数值(Visual Studio 中为   1)

                   介绍

             依次比较str1指向的字符串和str2指向的字符串的每一位,如果相同则继续往下比较,比较到'\0'仍旧相同,那么返回0;  如果有一次str1中的元素的ASCLL码值比str2的大返回一个大于0的值; 反之返回小于0的值。   


         5.strncpy

               char *   strncpy ( char *    destination, const char *    source, size_t    num );

             函数组成 

                            输入:1.char* destination:  需要拷贝的目标地址。          

                                       2.const char* source:   被拷贝的源地址。

                                       3.size_t num:  要拷贝的元素的个数。

                            返回值char*:  指向要拷贝元素的目标数组的地址(destination)。

                   介绍

贝source指向的字符串的num个元素到destination指向的地址。

有以下情况:1. num大于source的长度,多的部分会以'\0'填充直到num个。

                      2. num小于source的长度,拷贝source的前num个元素。

                   (情况2)注意:num小于source的长度时最后不会填充'\0'。


        6.strncat

              char *   strncat ( char *     destination, const char *    source, size_t    num );

             函数的组成

                             输入:1.char* destination:  需要拷贝的目标地址。          

                                        2.const char* source:   被拷贝的源地址。

                                        3.size_t num:  要拷贝的元素的个数。

                            返回值char*:  指向要拷贝元素的目标数组的地址(destination)。

                  介绍

               附加source的num个元素到destination的后方,覆盖最后的'\0'。

有以下情况:1. num大于source的长度,附加source元素直达末尾, 并加上'\0'。

                      2. num小于source的长度,附加num个source元素,并加上'\0'。

                     注意:拷贝的目标地址需要有字符串、有足够的空间。


         7.strncmp

                int   strncmp ( const char *    str1, const char *    str2, size_t    num );

               函数组成         

                              输入:1.const char* str1:  指向要判断的第一个字符串的首元素地址。

                                         2.const char* str2:   指向要判断的第二个字符串的首元素地址。

                                         3.size_t num:  比较的最多个数。

                           返回值int : 1.str1 < str2,返回<0的数值(Visual Studio 中为  -1)

                                                2.str1 = str2,返回0

                                                3.str1 > str2,返回>0的数值(Visual Studio 中为   1)

                   介绍

                   比较str1和str2指向的字符串最多num个元素。

           有以下情况:

          1.有一次str1中的元素的ASCLL码值比str2的大返回一个大于0 的值。

         (包括结束标志的比较)

          2.有一次str1中的元素的ASCLL码值比str2的小返回一个小于0 的值。

         (包括结束标志的比较)

          3.直到num个或同时到达两个字符串结束标志也没有出现上述情况则返回0。

         (实际上同时到达结束标志也进行了比较)


         8.strstr

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

            函数组成    

                         输入:1.const char* str1:  指向包含str2的被搜索字符串的首元素地址。

                                    2.const char* str2: 指向要查找的字符串的首元素地址。

                         返回值char* : 1.找到了返回指向str2第一次出现在str1中的字符串的首元素地址的指针

                                                    2.找不到返回NULL。

            介绍

           查找str2第一次出现在str1的位置,返回一个指向该位置首元素的指针,未找到返回NULL。


        9.strtok

                          char *    strtok ( char *    str, const char *    sep );

            函数组成

                       输入:1.char* str:  要被分割的目标字符串的指针。

                                  2.const char* sep:  指向分割符组成的字符串的指针。

              介绍

           sep指向的字符串内,存在若干个标记(分割符);函数的作用是对str指向的字符串按分隔符进行分割。具体分割方式如下:

             1.查找开头,第一次传入时,a.从str头部开始,找到第一个不是分隔符的字符作为开头。

                                  b.不是第一次传入,会从上一次结尾标记开始查找

             2.查找结尾,查找从开头开始第一个分隔符或者是结尾标志作为结尾,并作为标记记录。

             3.替换结尾字符并返回开头字符的地址。

             提醒:在两个连续的分隔符中间不会进行分割(从1.查找开头可以看出)


         10.strerror

                       char *    strerror ( int    errnum );

              函数组成

                         输入int errnum:  错误码,里面的值会随错误产生改变。

                         返回值:  返回指向错误信息的字符串指针。

              介绍

              配合返回错误信息字符串的首元素地址,主要配合printf打印错误信息,提高交互性。


          11.字符分类函数

          函数                如果他的参数符合下列条件就返回真
       iscntrl

                                   控制字符

(在ASCII码中,第0~31号及第127号(共33个)是控制字符)

       isspace

                空白字符:空格‘ ’,换页‘\f’,换行'\n',

                回车‘\r’,制表符'\t'或者垂直制表符'\v'

       isdigit

                                 十进制数字

                                       0~9

       isxdigit

                               十六进制数字

     包括所有十进制数字,小写字母a~f,大写字母A~F

       islower

                                 小写字母

                                     a~z

       isupper

                                 大写字母

                                     A~Z

       isalpha

                                    字母

                                a~z或A~Z

       isalnum

                             字母或者数字

                             a~z,A~Z,0~9

       ispunct

            标点符号,任何不属于数字或者字母的图形字符

                              (可打印)

      isgraph

                                图形字符

                                     

      isprint

                              可打印字符

                     包括图形字符和空白字符


         12.字符转换函数

                                         int    tolower  ( int    c );

                                         int    toupper  ( int    c );

              函数组成

                         输入:c:  对应字符的ASCLL码值。

                         返回值:  转换后的ASCLL码值。

              介绍

              大小写转换,虽然函数组成是传入int的ASCLL,实际上直接传入字符和直接使用返回值          作为字符也是可以的(隐式转化)。


         13.memcpy

          void *    memcpy ( void *    destination, const void *    source, size_t    num );

              函数组成

                         输入:1.void * destination: 指向要复制的目的空间的开头地址。

                                    2.const void * source:指向要被复制的源空间的开头地址。

                                    3.size_t num: 要复制的字节数。

                         返回值:  destination指向的地址。

              介绍

              与strncpy相似,不过是对每个字节进行复制,如果destination和source,在num个字节内有重叠,其复制结果是不确定的,一般的要求只是和strncpy一样,重复的位置被覆盖而达不到预期效果, 如有重叠可使用memmove函数,不过Visual Studio 2019中本函数没用这种问题。


        14.memmove

        void *    memmove ( void*    destination, const void *    source, size_t    num );

              函数组成

                         输入:1.void * destination: 指向要复制的目的空间的开头地址。

                                    2.const void * source:指向要被复制的源空间的开头地址。

                                    3.size_t num: 要复制的字节数。

                         返回值:  destination指向的地址。

              介绍

               与memcpy的差别在于memmove能够处理重叠地址。


         15.memcmp

          int    memcmp ( const void *    ptr1, const void *    ptr2, size_t    num );

               函数的组成         

                              输入:1.const void* ptr1:  指向要判断的第一个空间的首地址。

                                         2.const void* ptr2:   指向要判断的第二个空间的首地址。

                                         3.size_t num:  要比较的字节数。

                           返回值int : 1.ptr1 < ptr2,返回<0的数值(Visual Studio 中为  -1)

                                                2.ptr1 = ptr2,返回0

                                                3.ptr1 > ptr2,返回>0的数值(Visual Studio 中为   1)

               介绍

           比较ptr1和ptr2指向的空间最多num个字节。

           有以下情况:1.有一次ptr1中的字节比ptr2的大,ptr1 > ptr2

                                 2.有一次ptr1中的字节比ptr2的小,ptr1 < ptr2

                                 3.比较了num个字节都没有出现1,2情况,ptr1=ptr2;


二、函数的实现

所有实现仅供参考,并非唯一,也并不能保证绝对正确,请自行斟酌。

1.strlen

size_t mystrlen(const char* arr)
{
    assert(arr);
    int i = 0;
    while (*arr++)
    {
        i++;
    }
    return i;
}

有三种方式实现:1.计数器方法(本方法)

                             2.递归:没有递归到‘\0’就继续继续递归并返回1。

                             3.指针-指针:找到最后一位的指针,尾指针减头指针。

                              注意(3.):有类型指针相减返回的是两个指针中间该类型元素个数。


2.strcpy

char* mystrcpy(char* arr, const char* brr)
{
    assert(arr);
    char* farr = arr;
    while (*brr != 0)
    {
        *arr++ = *brr++;
    }
    *arr = '\0';//末尾标志
    return farr;
}


3.strcat

char* mystrcat(char* arr, char* brr)
{
    char* harr = arr;
    assert(arr);
    assert(brr);
    while (*arr)//这里不能用++
    {
        arr++;
    }
    while (*brr)
    {
        *arr++ = *brr++;
    }
    *arr = '\0';
    return harr;
}

       第一个循环是找打arr的末尾位置,注释部分是不能使用while(*arr++)这样在'\0'时arr还会++,导致指向'\0'下一位。

       第二个循环是复制。


4.strstr

char* mystrstr(const char* str1, const char* str2)
{
    assert(str1);
    assert(str2);
    char* hstr1 = str1;
    char* s1;
    char* s2;
    while (*hstr1)
    {
        s1 = hstr1;
        s2 = str2;
        while (*s2 && *s1 && *s1 == *s2)
        {
            s1++;
            s2++;
        }
        if (*s2 == '\0')
        {
            return hstr1;
        }
        hstr1++;
    }
    return NULL;
}

         本实现方法为暴力查找法,并不推荐,有更好的KMP算法。(如下)

KMP 算法详解 - 知乎 (zhihu.com)


5.strcmp

int mystrcmp(const char* arr, const char* brr)
{
    assert(arr);
    assert(brr);
    while (*arr == *brr)
    {
        if (*arr == '\0')//进到里面arr == brr,满足if说明同时到了结束
        {
            return 0;
        }
        arr++;
        brr++;
    }
    return *arr - *brr;
}

       如果没有退出while循环,说明它们两个始终相同(两个同时是‘\0’也会进入循环),退出循环说明有两方不同,直接相减可得到相差的ASCLL码值,作为返回值。


6.memcpy

void* mymemcpy(void* dest, const void* source, size_t num)
{
    void* hp = dest;
    assert(dest && source);
    while (num--)
    {
        *(char*)dest = *(char*)source;
        dest = (char*)dest + 1;
        source = (char*)source + 1;
    }
    return hp;
}

       除了类型转换与strncpy没有本质区别。(本实现没有像vs中一样解决重叠问题)


7.memmove

void* mymemmove(void* dest, const void* source, size_t num)
{
    assert(dest && source);
    void* hp = dest;
    int f = 0;
    if (dest > source)//源地址在前面,从后往前走
    {
        while (num--)
        {
            *((char*)dest + num) = *((char*)source + num);
        }
    }
    else//从前往后走
    {
        while (num--)
        {
            *(char*)dest = *(char*)source;
            dest = (char*)dest + 1;
            source = (char*)source + 1;
        }
    }
    return hp;
}

          和memcpy类似,不过需要判断dest和source是否重叠,怎样重叠来选择是从后往前复制,还是从前往后复制,来避免重叠导致的错误。

          1.来源在目标的前方,我们选择从后往前复制,这样复制时不会把目标未来要使用的覆盖。

          2.来源在目标的后方,选择从前往后复制。

例:

       上图是来源在后方我们拷贝4个字节内容,可以看到如果是a.从前往后第四次是需要覆盖掉source的第一位的,如果是b.从后往前第一次就会用第四位覆盖掉source的第一位,这样在使用source进行拷贝时候source的内容已经是被改变的source+3的内容了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值