C语言学习记录——삼십팔 字符串函数使用和剖析(2)

目录

一、strcmp

模拟实现

二、长度不受限制的函数:strcpy,strcat,strcmp

strncpy

追加函数strncat

strncmp

三、strstr


一、strcmp

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

1字符串大于2字符串,返回大于0的数字

1字符串小于2字符串,返回小于0的数字

相等返回0

int main()
{
    const char* p1 = "abcdef";
    const char* p2 = "qwert";
    int ret = strcmp(p1, p2);
    printf("%d\n", ret);
    return 0;
}

比较的方法并不是元素个数比大小,而是相应的元素比ANSCII码值,比如a和q比,a小于q,所以返回-1。

但是呢这是在vs里面进行的,不同的编译环境返回的数值不一样,但是范围还是一样,大于0,小于0,等于0。

模拟实现

int my_strcmp(const char* str1, const char* str2)
{
    assert(str1 && str2);
    while (*str1 == *str2)
    {
        if (*str1 == '\0')
        {
            return 0;
        }
        str1++;
        str2++;
    }
    if (*str1 > *str2)
        return 1;
    else if(*str1 < *str2)
        return -1;
}

int main()
{
    const char* p1 = "abcdef";
    const char* p2 = "abqwe";
    int ret = my_strcmp(p1, p2);
    printf("ret = %d\n", ret);
    return 0;
}

如果abc和abcd比较,那么循环到\0和d比较,不一样,就来到下面的if else,0小于d,返回-1。

或者if else改成return (*str1 - *str2)也可。

二、长度不受限制的函数:strcpy,strcat,strcmp

读取到\0才停止,但是这样有不安全,比如strcpy函数,如果目的地不足够长于源头字符串,但是还是拷贝过去了,会形成非法访问,所以不安全。还有长度限制的函数:strncpy,strncat,strncmp。

strncpy

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

count也就是要拷贝几个字节,单位是字节。比如

int main()
{
    char arr1[10] = "abcdef";
    char arr2[] = "hello bit";
    strncpy(arr1, arr2, 4);
    return 0;
}

拷贝4个字节,\0不会被拷贝过去。当指定的个数大于源字符串大小,剩下的就补\0,直到指定的字节个数。

关于这个函数,是这样定义的

char* _cdecl strncpy(char* dest, const char* source, size_t count)
{
    char* start = dest;
    while (count && (*dest++ = *source++))/* copy string*/
        count--;
    if (count)/* pad out with zeroes*/
        while (--count)
            *dest++ = '\0';
    return(start);
}

同样的,其他两个也是原先基础上加上字节个数

追加函数strncat

追加后,还会再最后自动加一个\0,因为最终要追加成一个字符串。如果count大于追加过去的字符串个数,那么追加完在后面放上一个\0,追加就结束了,不会在后面放上好几个\0

定义

char* _cdecl strncat(char* front, const char* back, size_t count)
{
    char* start = front;
    while (*front++)
        front--;
    while (count--)
        if (!(*front++ = *back++))
            return(start);
    *front = '\0';
    return(start);
}

strncmp

也就是比较几个字符,数值也就不一样。

三、strstr

char* strstr(const char*, const char*)

int main()
{
    const char* p1 = "abcdef";
    const char* p2 = "def";
    const char* ret = strstr(p1, p2);
    if (ret == NULL)
    {
        printf("子串不存在\n");
    }
    else
    {
        printf("%s\n", ret);
    }
    return 0;
}

函数找不到就会返回空指针,找到会返回d的地址,用指针变量ret接收后,会从d开始往后打印,如果此时p1是abcdefgh,那么结果就会出来abcdefgh。如果p1是abcdefabcdef,有两个def,那么结果会从第一个开始。

模拟实现

#include <stdio.h>
#include <assert.h>

const char* my_strstr(const char* p1, const char* p2)
{
    assert(p1 != NULL);
    assert(p2 != NULL);
    const char* s1 = p1;
    const char* s2 = p2;
    const char* cur = p1;
    if (*p2 == '\0')
    {
        return p1;
    }
    while (*cur)
    {
        s1 = cur;
        s2 = (char*)p2;
        while ((*s1 != '\0') && (*s2 != '\0') && (*s1 == *s2))
        {
            s1++;
            s2++;
        }
        if (*s2 == '\0')
        {
            return cur;
        }
        cur++;
    }
    return NULL;
}

int main()
{
    const char* p1 = "abcdefgh";
    const char* p2 = "def";
    const char* ret = strstr(p1, p2);
    if (ret == NULL)
    {
        printf("子串不存在\n");
    }
    else
    {
        printf("%s\n", ret);
    }
    return 0;
}

最好画图才能明白。库函数的定义是

char* my_strstr(const char* str1, const char* str2)
{
    char* cp = str1;
    char* s1, * s2;
    if (!*str2)
        return((char*)str1);
    while (*cp)
    {
        s1 = cp;
        s2 = (char*)str2;
        while (s1 && s2 && !(*s1 - *s2))
            s1++, s2++;
        if (!*s2)
            return(cp);
        cp++;
    }
    return (NULL);
}

但是VS2019这里查得严,cp,s1,s2,函数类型都得是const char*才行。

其实还可以第一个写的为基础再优化。在s2的if语句后再写这个

if (*s1 == '\0')
{
    return NULL;
}

结束。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值