C语言str函数的源码

str函数的源码

1、strcpy函数

  1. 原型char * strcpy(char * destin, const char * source)
  2. 作用:把source指向的字符串拷贝到destin指向的字符串中
  3. 代码
char * my_strcpy(char * destin, const char * source)
{
    /***把source指向的字符串拷贝到destin指向的字符串中***/
    assert(destin != NULL && source != NULL);  //检查source和destin的指向是否为空
    char *tmp = destin;

    do {
        *destin++ = *source++
    }while(*destin && *source);  //将source指向的字符复制给destin指向的字符

    return tmp;  //返回指向最终结果的指针
}

int main()
{
    char destination[100] = {1};
    const char *source = "abcdefgh";

    char *destion = my_strcpy(destination, source);
    printf("%s\n", destion);

    return 0;
}

2、strncpy函数

  1. 原型char * strncpy(char * str1, char * str2, int count)
  2. 作用:把str2指向的前count个字符拷贝到str1指向的字符串中
  3. 代码
#include <stdio.h>
#include <string.h>
#include <assert.h>

char * my_strncpy(char * str1, char * str2, int count)
{
    assert(str1 != NULL);  //检验str1是否为空
    while(count && (*str1++ = *str2++))  //把str2的前n个字符复制给str1
    {
        count--;  //长度随着复制的进行而减少
    }
    while(count--)
    {
        *str1++ = '\0';  //如果str2的长度小于count那就用NULL填充str1的剩余
    }
    return str1;
}

int main()
{
    char destination[10] = {0};
    char *source = "abcdefgh";
    int count = 5;

    my_strncpy(destination, source, count);
    printf("%s\n", destination);
    return 0;
}

3、strcmp函数

  1. 原型int strcmp(const char * str1, const char * str2)
  2. 作用:比较str1和str2,str1 > str2返回1,str1 == str2返回0
  3. 代码
int my_strcmp(const char * str1, const char * str2)
{
    /***比较str1和str2,str1 > str2返回大于0的数,str1 == str2返回0,str1 < str2返回小于0的数***/
    while( ! ((*str1 != *str2) && str1 != '\0'))
    {
        //如果str1和str2的字符相等且字符str1没有到末尾则进入循环
        str1++;  //指针str1向后加一位
        str2++;  //指针str2向后加一位
    }
    return (*str1 - *str2);  //返回跳出循环的str1和str2当前的字符的差值比较的结果(0或1或-1)
}

int main()
{
    char *buf1 = "aaaa",
         *buf2 = "aaaab",
         *buf3 = "aaaac";
    int ptr = 0;  //定义变量用来存放my_strcmp返回的值

    ptr = my_strcmp(buf2, buf1);
    if (ptr > 0)
        printf("string 2 is bigger than string 1\n");
    else
        printf("string 2 is smaller than string 1\n");

    ptr = my_strcmp(buf2, buf3);
    if (ptr > 0)
        printf("string 2 is bigger than string 3\n");
    else
        printf("string 2 is smaller than string 3\n");

    return 0;
}

4、strncmp函数

  1. 原型int strncmp(const char * str1, const char * str2, int count)
  2. 作用:比较str1和str2的前n个字符
  3. 代码
int my_strncmp(const char * str1, const char * str2, int count)
{
    /***比较str1和str2的前n个字符***/
    if(!count)
        return 0;
    while(--count && *str1 && *str1 == *str2)
    {
        str1++;
        str2++;
    }
    return (*str1 - *str2);
}

int main()
{
    char *str1 = "China is a nation!";
    char *str2 = "French is a nation!";
    int count = 5,
        ptr = 0;

    ptr = my_strncmp(str1, str2, count);
    if(ptr != 0)
        printf("str1 is not equal to str2!\n");
    return 0;
}

5、stricmp函数

  1. 原型int my_stricmp(const char *str1, const char *str2)
  2. 作用:不区分大小写的比较str1和str2
  3. 代码
int my_stricmp(const char *str1, const char *str2)
{
    /***不区分大小写的比较str1和str2***/
    char ch1 = '0',
         ch2 = '0';

    do
    {
        if((ch1 = (unsigned char)(*(str1++))) >= 'A' && ch1 <= 'Z')
            ch1 += 0x20;
        if((ch2 = (unsigned char)(*(str2++))) >= 'A' && ch2 <= 'Z')
            ch2 += 0x20;
    }while(ch1 && (ch1 == ch2));  // 判断是否相等且str1不为'\0',是则进入循环
    return (ch1 - ch2);  //返回两个数的大小
}

int main()
{
    char *str1= "ammana";
    char *str2 = "bibi";
    char *str3 = "AMMANA";
    int ptr = 0,
        ptr1 = 0;

    ptr = my_stricmp(str1, str2);
    if(ptr > 0)
        printf("str1 bigger than str2!\n");
    else
        printf("str1 smaller than str2!\n");

    ptr1 = my_stricmp(str1, str3);
    if(ptr1 > 0)
        printf("str1 bigger than str3!\n");
    else if(ptr1 < 0)
        printf("str1 smaller than str3!\n");
    else
        printf("str1 equal to str3!\n");

    return 0;
}

6、strlen函数

  1. 原型unsigned int strlen(const char * str)
  2. 作用:计算str的长度并返回
  3. 代码
unsigned int my_strlen(const char * str)
{
    /***计算str的长度并返回***/
    unsigned length = 0;  //定义无符号变量length统计str的长度
    while(*str != '\0')  //判断str指向的字符是否为'\0'
    {
        length++;  //长度加1
        str++;  //指向的地址向后加1位
    }
    return length;
}

int main()
{
    char * str = "abcdefgh";
    int len = 0;

    len = my_strlen(str);

    printf("%d\n", len);
    return 0;
}

7、strcat函数

  1. 原型char * strcat(char* destin, const char *source)
  2. 作用:连接两个字符串,将source连接到destin
  3. 代码
char * my_strcat(char* destin, const char *source)
{
    /***连接两个字符串,将source连接到destin***/
    char * temp = destin;  //定义temp指针变量存放destin的地址

    while(*temp)  //判断temp字符串是否读到了'\0'
    {
        temp++;  //将temp指针读到字符串末尾
    }

    while(*temp++ = *source++)  //把source字符串从temp末尾开始复制给temp
        {};

    return temp;  //返回链接好的字符串的指针
}

int main()
{
    /***对函数Strcat的调用***/
    char destination[25];  //定义一个大小为25的数组
    char *space = " ",
         *String = "C++!",
         *Hello = "Hello";

    strcpy(destination, Hello);  //进行拷贝
    my_strcat(destination, space);
    my_strcat(destination, String);

    printf("%s\n", destination);  //打印最终结果
    return 0;
}

8、strchr函数

  1. 原型char * strchr(char * str, const char c)
  2. 作用:查找str中c首次出现的位置,并返回位置或者NULL
  3. 代码
char * my_strchr(char * str, const char c)
{
    /***查找str中c首次出现的位置,并返回位置或者NULL***/
    while(*str != '\0' && *str != c)  //判断str是否为'\0'且等于c
    {
        str++;
    }
    //判断如果str等于c则返回与c匹配的str否则返回NULL
    return (*str == c ? str : NULL);
}

int main()
{
    char * string = "abcdefgh";
    char c = 'd',
         *ptr = NULL,  //存放my_strchr的返回值

    ptr = my_strchr(string, c);
    if(ptr)
        printf("%c\n", c);
    else
        printf("Not Found!\n");

    return 0;
}

9、strrchr函数

  1. 原型char * strrchr(char * str, const char c)
  2. 作用:查找str中c最后一次出现的位置,并返回位置或者NULL
  3. 代码
char * my_strrchr(char * str, const char c)
{
    /***查找str中c最后一次出现的位置,并返回位置或者NULL***/
    char * end = str + strlen(str);  //定义指针end存放str的末尾地址

    while(*str != *end && *end != c)  //判断end没有到头部且没找到和c匹配的字符
    {
        end--;  //向前进行移动
    }

    if(*end == *str && *end != c)  //如果没找到则返回NULL
        return NULL;

    return end;
}

int main()
{
    char * string = "abcdefgh";
    char c = 'd',
         *ptr = NULL,  //存放my_strchr的返回值

    ptr = my_strrchr(string, c);
    if(ptr)
        printf("%c\n", c);
    else
        printf("Not Found!\n");

    return 0;
}

10、strrev函数

  1. 原型char * strrev(char * str)
  2. 作用:翻转字符串并返回字符串指针
  3. 代码
char * my_strrev(char * str)
{
    /***翻转字符串并返回字符串指针***/
    assert(str != NULL);
    char *end = str;
    char *head = str;
    char temp = '0';

    while(*end++)
    {};

    end--;  /* 与end++抵消 */
    end--;  /* 回跳过结束符'\0' */

    /* 当head和end未重合时,交换它们所指向的字符 */
    while(head < end)
    {
        temp = *head;
        *head++ = *end;  /* head向尾部移动 */
        *end-- = temp;  /* end向头部移动 */
    }
    return str;
}

#if 0
/*第二种实现方式*/
char * my_strrev(char * str)
{
    /***翻转字符串并返回字符串指针***/
    assert(str != NULL);
    char *end = strlen(str) + str -1;
    char temp = '0';

    while(str < end)
    {
        temp = *str;
        *str = *end;
        *end = temp;
        str++;
        end--;
    }
    return str;
}
#endif


int main()
{
    /***只能逆置字符数组,而不能逆置字符串指针指向的字符串,
        因为字符串指针指向的是字符串常量,常量不能被修改***/
    char str[] = "Hello World";  //定义str数组

    printf("Before reversal: %s\n", str);
    my_strrev(str);
    printf("After reversal:  %s\n", str);
    return 0;
}

11、strdup函数

  1. 原型char * strdup(const char * str)
  2. 作用:拷贝字符串到新申请的内存中返回内存指针,否则返回NULL
  3. 代码
#include <assert.h>

char * my_strdup(const char * str)
{
    /***拷贝字符串到新申请的内存中返回内存指针,否则返回NULL***/
    char * temp = (char*)malloc(strlen(str) + 1);  //给temp申请内存
    assert(str != NULL && temp != NULL);  //进行检查是否为NULL
    strcpy(temp, str);  //进行拷贝
    return temp;  //返回的内存在堆中需要手动释放内存
}

int main()
{
    char *str = NULL,
         *string = "abcde";

    str = my_strdup(string);
    printf("%s\n", str);
    free(str);  //释放内存

    return 0;
}

12、strstr函数

  1. 原型char * strstr(const char * str1, char * str2)
  2. 作用:查找str2在str1中出现的位置,找到返回位置,否则返回NULL
  3. 代码
char * my_strstr(const char * str1, char * str2)
{
    /***查找str2在str1中出现的位置,找到返回位置,否则返回NULL***/
    assert(str1 != NULL & str2 != NULL);  //检查str1和str2
    int len1 = strlen(str1);  //定len1来获取str1的长度
    int len2 = strlen(str2);  //定len2来获取str2的长度

    while(len1 >= len2)  //必须str1的长度大于str2的长度
    {
        len1--;  //str1的长度每一次减去一个
        if(!strncmp(str1, str2, len2))  //进行比较str2和str1的前len2个字符
        {
            return str2;  //如果匹配返回str2
        }
        str1++;  //str1每一次都要向后走一步
    }
    return NULL;
}

int main()
{
    char *str1 = "China is a nation!",
         *str2 = "nation",
         *ptr = NULL;

    ptr = my_strstr(str1, str2);
    printf("The string is: %s\n", ptr);
    return 0;
}

13、strpbrk函数

  1. 原型char *strpbrk(const char *str1, const char *str2)
  2. 作用:从str1的第一个字符向后检索,直到’\0’,如果当前字符存在于str2中,那么返回当前字符的地址,并停止检索.
  3. 代码
#include <assert.h>

char *my_strpbrk(const char *str1, const char *str2)
{
    /***strpbrk()从str1的第一个字符向后检索,直到'\0',如果当前字符存在于str2中,
        那么返回当前字符的地址,并停止检索***/
    assert(str1 != NULL && str2 != NULL);
    const char *str3 = str2;

    while(*str1)  //判断石头人字符串str1是否结束
    {
        for(str3 = str2; *str3; ++str3)  //str2进行循环与str1的自费比较
        {
            if(*str1 == *str3)  //如果相等则进行str1的下一个判断
                break;
        }
        if(*str3)  //如果str3结束则结束比较
            break;
        str1++;
    }

    if(*str3 == '\0')  //如果str1到末尾则返回NULL
        str1 = NULL;
    return (char*)str1;
}

int main()
{
    char s1[] = "http://see.xidian.edu.cn/cpp/u/xitong/";
    char s2[] = "see";
    char *p = my_strpbrk(s1, s2);
    if(p)
    {
        printf("The result is: %s\n",p);
    }
    else
    {
        printf("Sorry!\n");
    }
    return 0;
}

14、strspn函数

  1. 原型int my_strspn(const char *str1, const char *str2)
  2. 作用:从参数str1字符串的开头计算连续的字符,而这些字符都完全是str2所指字符串中的字符。
  3. 代码
#include <assert.h>

/***strspn()函数检索区分大小写***/
int my_strspn(const char *str1, const char *str2)
{
    /***从参数str1字符串的开头计算连续的字符,而这些字符都完全是str2所指字符串中的字符。
    简单的说,若strspn()返回的数值为n,则代表字符串str1开头连续有n个字符都是属于字符串str2内的字符***/
    assert(str1 != NULL && str2 != NULL);
    const char *tmp = str1;  //临时变量存储str1的地址
    const char *str3;

    while(*tmp)
    {
        for(str3 = str2; *str3; ++str3)
        {
            if(*str3 == *tmp)  //判断str1是否存在str2的字符
                break;
        }
        if(*str3 == '\0')  //如果str2结束则跳出循环str1++
            break;
        tmp++;
    }

    return tmp - str1;  //返回差值,即str1共有几个连续的字符是str2中存在的
}

int main()
{
    char s1[] = "hello world!";
    char s2[] = "i am lihua";

    int p = my_strspn(s1, s2);

    printf("The result is:%d\n", p);
    return 0;
}

15、strtok函数

  1. 原型char *my_strtok(char *sou, char *delim)
  2. 作用:将字符串分割成一个个片段
  3. 代码
/***因strtok函数内部使用了静态指针,因此它不是线程安全的***/
static char *olds;  //定义全局变量来进行定位
char *my_strtok(char *sou, char *delim)
{
    /***strtok函数用来将字符串分割成一个个片段,
    在参数sou的字符串中发现到参数delim的分割字符时则会将该字符改为\0 字符***/
    //参数sou指向欲分割的字符串,参数delim为分割字符串
    //在第一次调用时,strtok()必需给予参数sou字符串,往后的调用则将参数sou设置成NULL
    //每次调用成功则返回下一个分割后的字符串指针

    char *token = NULL;
    if(sou == NULL)  //如果sou为空则将上一次的位置给sou
    {
        sou = olds;
    }

    /*将指针移到第一个非delim的位置*/
    sou += strspn(sou, delim);
    if(*sou == '\0')  //如果是结束符,则将结束符保存并退出函数
    {
        olds = sou;
        return NULL;
    }

    /*获取delim的字符在字符串sou中第一次出现的位置*/
    token = sou;
    sou = strpbrk(token, delim);

    if(sou == NULL)
    {
        olds = __rawmemchr (token, '\0');  //参考http://dev.wikl.net/89401.html
    }
    else
    {
        *sou = '\0';  //将分隔符的位置用'\0'替换
        olds = sou + 1;  //将olds指向下一次需要操作的位置
    }
    return token;
}

int main()
{
    //strtok处理的是函数的局部状态信息,所以不能同时解析两个字符串
    char sou[100] = " Micael_SX is so good";
    char *delim = " ";
    char *token;
    token = my_strtok(sou, delim);
    while(token != NULL)
    {
        printf("%s\n", token);
        token = my_strtok(NULL, delim);
    }
    return 0;
}

16、strsep函数

  1. 原型char *my_strsep(char **stringp, const char *delim)
  2. 作用:将字符串分割成一个个片段
  3. 代码
/***********************************************************
a:如果*stringp为NULL,则该函数不进行任何操作,直接返回NULL;
b:strsep每次都是从*stringp指向的位置开始搜索,搜索到任一分割字符之后,将其置为’\0’,
   并使*stringp指向它的下一个字符。如果找不到任何分割字符,则将*stringp置为NULL。
c:strsep内部没有使用静态指针,因而strsep是线程安全的。
d:strsep返回的子串有可能是空字符串,实际上,就是因为strtok无法返回空子串,才引入的strsep函数。
   不过strtok符合C89/C99标准,因而移植性更好。但strsep却不是。
e: "二八定律",即80%情况下分隔符只有一个字节,使用strchr完成,20%情况有多个字节,调用strpbrk完成
*************************************************************/

char *my_strsep(char **stringp, const char *delim)
{
    /***strsep函数用来将字符串分割成一个个片段***/
    char *begin,
         *end;
    begin = *stringp;
    if(begin == NULL)
    {
        return NULL;
    }

    /*delim分隔符是单个字符的情况是非常频繁的,因此不需要使用代价昂贵的strpbrk函数
     而只需要调用strchr就能解决*/
    if(delim[0] == '\0' || delim[1] == '\0')
    {
        char ch = delim[0];
        if(ch == '\0')
        {
            end = NULL;
        }
        else
        {
            if(*begin == ch)
            {
                end = begin;
            }
            else if(*begin == '\0')
            {
                end = NULL;
            }
            else
            {
                end = strchr(begin + 1, ch);
            }
        }
    }
    else
    {
        /*delim有两个字符以上,才调用strpbrk*/
        end = strpbrk(begin, delim);
    }

    if(end)
    {
        /*用0封闭这个token;返回stringp,指向一个null指针*/
        *end++ = '\0';
        *stringp = end;
    }
    else
    {
        /*没有出现delim,这是最后一个token*/
        *stringp = NULL;
    }
    return begin;
}

int main()
{
    char source[] = "hello, world! welcome to China!";
    char delim[] = " ,!";

    char *s = strdup(source);
    char *token;
    for(token = my_strsep(&s, delim); token != NULL; token = my_strsep(&s, delim))
    {
        printf(token);
        printf("+");
    }
    printf("\n");
    return 0;
}

参考文章

链接:

  1. http://blog.csdn.net/kangroger/article/details/24383571
  2. http://zheng-ji.info/blog/2014/02/05/shen-ru-strtokhan-shu/
  3. http://blog.csdn.net/gqtcgq/article/details/48399957
  • 5
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值