C语言 详解字符函数和字符串函数以及实现

本文详细介绍C语言中字符串处理函数,包括strlen、strcpy、strcat、strcmp、strncpy、strncat、strncmp、strstr、strtok等,以及错误处理和内存操作函数如strerror、perror、memcpy、memmove和memcmp,适合初学者和进阶者学习

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、求字符串长度

1.1 strlen函数

1.1.1 strlen实现

二、长度不受限制的字符串函数

 2.1 strcpy函数

2.1.1 strcpy实现

 2.2 strcat函数

2.2.1 strcat实现

2.3 strcmp函数 

2.3.1 strcmp实现

三、长度受限制的字符串函数

3.1 strncpy函数

3.2 strncat函数

3.3 strncmp函数

四、字符串查找

4.1 strstr函数

4.1.1 strstr实现

4.2 strtok函数

五、错误信息报告

5.1 strerror函数

5.2 perror函数

六、内存操作函数

6.1 memcpy函数

6.1.1 memcpy实现

6.2 memmove函数

6.3 memcmp函数


一、求字符串长度

1.1 strlen函数

用法:该函数主要用来求字符串的长度(不含\0),引用头文件为<string.h>

#include<stdio.h>
#include<string.h>
int main()
{
    char str1[]="abcd";
    int ret=strlen(c);
    printf("%d ",ret);
    printf("\n");
    return 0;
}

输出结果为:4

1.1.1 strlen实现

由此可知,我们遇到\0停止,我们在看看C语言是何如定义这个标准的。

这里用const的原因是更加安全可以保证不被修改,因为我们只需要长度。

#include<stdio.h>
size_t my_strlen(const char* str1)
{
    int count=0;
    while(*str1++!='\0')
    count++;
    return count;
}
int main()
{
    char str1[]="work hard";
    int ret=my_strlen(str1);
    printf("%d\n",ret);
    return 0;
}

二、长度不受限制的字符串函数

 2.1 strcpy函数

用法:该函数可以把源字符串拷贝到目的地,并且会在目标字符串自动追加\0,引用头文件为<string.h>

#include<stdio.h>
#include<string.h>
int main()
{
    char str1[]="workhard";
    char str2[]="xxxx";
    strcpy(str1,str2);
    printf("%s",str1);
    printf("\n");
    return 0;
}

输出结果为:xxxx

我们通过调试可以更清楚的看到:

 

2.1.1 strcpy实现

由此可知,这里是把源字符串拷贝过去后,再加上\0,C语言是这样定义标准的:

这里我们的源字符串定义为const是保证源字符串不被修改。

#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
    //防止遇到空字符串
    assert(dest && src);
    char* tmp = dest;
    while((*dest++=*src++)!='\0')
    ;
    return tmp;
}
int main()
{
    char arr1[10] = "abcdef";
    char arr2[] = "123";
    char*p=my_strcpy(arr1,arr2);
    printf("%s\n", p);
    return 0;
}

 2.2 strcat函数

用法:在字符串末尾追加字符串,引用头文件<string.h>

#include<stdio.h>
#include<string.h>
int main()
{
    //这里记得给大小!要超出追加后的长度
    char str1[30]="workhard";
    char str2[]="xxxx";
    strcat(str1,str2);
    printf("%s",str1);
    printf("\n");
    return 0;
}

输出结果为:workhardxxxx

2.2.1 strcat实现

由此可知,我们是在目标字符串的末尾继续追加,那么我们首先就要找到目标字符串的的末尾,即\0,C语言是这样规定的:

用const修饰源字符串是为了保证不被修改。

#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
    //避免为字符串为空
    assert(dest && src);
    char* tmp = dest;
    while((*dest++=*src++)!='\0')
    ;
    return tmp;
}
int main()
{
    char arr1[10] = "abcdef";
    char arr2[] = "123";
    char*p=my_strcpy(arr1,arr2);
    printf("%s\n", p);
    return 0;
}

2.3 strcmp函数 

用法:比较字符串的大小,如果大于返回>0的数,等于返回0,小于返回<0的数。

#include<stdio.h>
#include<string.h>
int main()
{
    char str1[]="work hard";
    char str2[]="ab";
    int ret=strcmp(str1,str2);
    printf("%d",ret);
    printf("\n");
    return 0;
}

 输出结果为:22(此结果依照不同编译器生成不同的结果,但是一定是>0的数字)

2.3.1 strcmp实现

由此可知,我们是选取字符串中每一个字符进行比较,C语言是这样定义的:

 

#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* str1, const char* str2)
{
    assert(str1&&str2);
    while(*str1==*str2)
    {
        if(*str1=='\0')
        {
          return 0;
        }
        str1++;
        str2++;
    }
    //直接返回大小,要么是0,要么是负数,要么大于0
    return *str1-*str2;
}
int main()
{
    char str1[] = "abcdef";
    char str2[] = "abcg";
    int ret=my_strcmp(arr1,arr2);
    printf("%d\n", ret);
    return 0;
}

三、长度受限制的字符串函数

3.1 strncpy函数

用法:和strcpy函数一样,但是可以加上想要复制的个数。

#include<stdio.h>
#include<string.h>
int main()
{
    char str1[]="work hard";
    char str2[]="ab";
    strncpy(str1,str2,2);
    printf("%s",str1);
    printf("\n");
    return 0;
}

输出结果为:abrk hard

tips:该字符串可以用来拷贝自己,但是strcpy不可以!

#include<stdio.h>
#include<string.h>
int main()
{
    char str1[]="work hard";
    strncpy(str1,str1+5,4);
    printf("%s",str1);
    printf("\n");
    return 0;
}

输出结果为:hard hard

3.2 strncat函数

用法:和strcmp函数一样,不过可以选择比较的个数。

#include<stdio.h>
#include<string.h>
int main()
{
    char str1[20]="workhard";
    char str2[]="hard";
    strncat(str1,str2,3);
    printf("%s",str1);
    printf("\n");
    return 0;
}

输出结果为:workhardhar

3.3 strncmp函数

用法:和strcmp函数一样,不过可以选择比较的个数。

#include<stdio.h>
#include<string.h>
int main()
{
    char str1[20]="workhard";
    char str2[]="ward";
    int ret=strncmp(str1,str2,1);
    printf("%d ",ret);
    printf("\n");
    return 0;
}

输出结果为:0

四、字符串查找

4.1 strstr函数

用法:寻找匹配的字符串,返回找到的第一个地址。

#include<stdio.h>
#include<string.h>
int main()
{
    char str1[20]="workhard";
    char str2[]="har";
    char* ret=strstr(str1,str2);
    printf("%s",ret);
    printf("\n");
    return 0;
}

输出结果为:hard

4.1.1 strstr实现

这里我们采用bf方法,因为这个是偏向入入门的教程,想了解kmp方法请看我之前的博客。

【超详细】kmp算法,直击本质_努力敲代码的小王的博客-优快云博客

我们先来看看C语言是如何规定这个函数的:

 

#include<stdio.h>
#include<string.h>
char* my_strstr(const char* str1,const char* str2)
{
    const char* s1=str1;
    const char* s2=str2;
    const char* p=str1;
    while(*p)
    {
        //不想等的时候p会往下走,当*s1=*s2时,p会记录第一个想等的位置
        s1=p;
        s2=str2;
        //如果相等就一直往下走
        while(*s1!='\0'&&*s2!='\0'&&*s1==*s2)
        {
            s1++;
            s2++;
        }
        if(*s2=='\0')
        {
            return (char*)p;
        }
        p++;
    }
    return NULL;
}
int main()
{
    char str1[20]="workhard";
    char str2[]="har";
    char* ret=my_strstr(str1,str2);
    printf("%s",ret);
    printf("\n");
    return 0;
}

4.2 strtok函数

用法:可以分割字符串,该用法比较难以解释,直接看例子会比较好。

 

#include<stdio.h>
#include<string.h>
int main()
{
    char str1[]="xiaowang@163.com";
    char str2[]="@.";
    //strtok函数的第一个参数不为NULL
    char* ret=strtok(str1,str2);
    printf("%s",ret);
    printf("\n");
    //strtok函数中有静态变量会保存下一个位置,所以这次用NULL指针
    ret=strtok(NULL,str2);
    printf("%s",ret);
    printf("\n");
    ret=strtok(NULL,str2);
    printf("%s",ret);
    printf("\n");
    return 0;
}

输出结果为:xiaowang

                       163

                       com

五、错误信息报告

5.1 strerror函数

用法:可以报告错误,需要结合printf来打印错误信息。

 

#include<stdio.h>
#include<string.h>
//必须包含的头文件
#include<errno.h>
int main()
{
    FILE* pfile;
    pfile=fopen("abc.txt","r");
    if(pfile==NULL)
    {
        printf("%s",strerror(errno));
    }
    return 0;
}

输出结果为:No such file or directory

5.2 perror函数

用法:相当于printf+strerror

#include<stdio.h>
#include<string.h>
//必须包含的头文件
#include<errno.h>
int main()
{
    FILE* pfile;
    pfile=fopen("abc.txt","r");
    if(pfile==NULL)
    {
        perror("error");
        //printf("%s",strerror(errno));
    }
    return 0;
}

输出结果为:error:No such file or directory

六、内存操作函数

6.1 memcpy函数

用法:其实就是strncpy函数,只不过它可以接受任意类型,不限于char类型。

我们可以从C语言定义的标准中看出来:

这里是void*类型,void*类型可以接受任意类型。

#include<stdio.h>
#include<string.h>
int main()
{
    int arr1[]={1,2,3,4,5};
    int arr2[]={6,7,8,9,10};
    memcpy(arr1,arr2,8);
    int i=0;
    for(i=0;i<5;i++)
    {
        printf("%d ",arr1[i]);
    }
}

 输出结果为:6,7,3,4,5,1 

6.1.1 memcpy实现

要实现这个函数并不难,我们首先要知道一个概念,char*类型一次走一个字节!!!学会指针这个应该不难理解,所以我们需要把void*类型强制转化问char*类型,保证了不管什么类型传过来,我们都走一个字节。

#include<stdio.h>
#include<string.h>
void* my_memcpy(void* dest,const void* src,size_t num)
{
    void* ret=dest;
    //如果目标地址在后面,src需要从后向前赋值
    if(dest>src)
    {
        while(num--)
        {
        *((char*)dest+num)= *((char*)src+num);
        }
    }
    //如果目标地址在前面,或者不重叠,src从前向后赋值
    else
    {
        while(num--)
        {
        *(char*)dest=*(char*)src;
        dest=(char*)dest+1;
        src=(char*)src+1;
        }
    }
    return ret;
}
int main()
{
    int arr1[]={1,2,3,4,5,6};
    int arr2[10]={0};
    my_memcpy(arr1+2,arr1,12);
    int i=0;
    for(i=0;i<6;i++)
    printf("%d ",arr1[i]);
    printf("\n");
    return 0;
}

6.2 memmove函数

用法:memcpy函数有一个缺点,就是不能自己复制自己,但是memmove函数可以,不过我们用的编译器把memmove函数干的事情也集成到了memcpy函数中,这里只说用法,实现就是memcpy函数。

#include<stdio.h>
#include<string.h>
int main()
{
    int arr1[]={1,2,3,4,5,6,8};
    int arr2[]={6,7,8,9,10};
    memmove(arr1,arr1+2,16);
    int i=0;
    for(i=0;i<7;i++)
    {
        printf("%d ",arr1[i]);
    }
}

输出结果为:3 4 5 6 5 6 8 

6.3 memcmp函数

用法:用法和strncmp函数一样,不过它可以接受任意类型! 

#include<stdio.h>
#include<string.h>
int main()
{
    int arr1[]={1,2,3,4,5,6,8};
    int arr2[]={1,2,8,9,10};
    int ret=memcmp(arr1,arr2,8);
    printf("%d ",ret);
}

 输出结果为:0

到这里就介绍完了,有些函数的实现没有写,是因为整体做法差不多,我只列举了比较难实现的一些函数,如果错误希望指正!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值