C语言字符串函数<string.h>(部分)

string.h

介绍

<string.h>是C语言标准库一个常用的头文件,在使用时我们要引入头文件(#include <string.h>)常用来做字符串的处理,比较……,本文介绍了比较常用的函数

函数功能简介
strlen返回字符串长度
strcpy复制字符串
strncpy复制字符串前n个字符
strcat把一个字符串后追加到另一个字符串后
strncat把一个字符串的 n 个字符后追加到另一个字符串后
strcmp比较两个字符串的ASCII
strncmp比较两个字符串的前 n 个字符的ASCII
strstr在一个字符串中查找另一个字符串
strtok根据输入内容分割字符串
strerror将错误码转换成错误信息
memcpy拷贝不折叠的内存
memmove可以拷贝折叠的内存
memcmp内存块内容比较
memset以字节为单位设置内存

1.strlen()

一般使用

函数原型:size_t strlen ( const char * str );

//返回str的长度
#include <stdio.h>
#include <string.h>

int main()
{
    char arr[] = {'1','2','3'};
    int len1 = strlen(arr); 
//		int len1 = my_strlen(arr);//模拟实现
    printf("%d\n", len1);//得到的结果是3
    return 0;
}

模拟实现

int my_strlen(const char* str)//const 能够让代码更加健壮
{
    int count = 0;
    assert(str != NULL);//判断str的首元素地址是否为NULL,是则直接退出,需要引用头文件<assert.h>
    while(*str != '\0')//字符串的结束标识为'\0',当没有遇到'\0'时执行
    {
        count++;//长度+1
        str++;//进入下一个元素地址
    }
    return count;
}

2.strcpy()

一般使用

函数原型:char * strcpy ( char * destination, const char * source );
返回的是destination的地址

#include <stdio.h>
#include <string.h>

int main()
{
    char arr[20] = {0};
    strcpy(arr, "hello");//strcpy()的结束标识为'\0'
//		my_strcpy(arr, "hello");//模拟实现
    printf("%s\n",arr);//打印结果为:hello
    return 0;
}

模拟实现

char * my_strcpy(char * dst,const char * src)
{
	assert(src);//判断src的首元素地址是否为NULL,是则直接退出,需要引用头文件<assert.h>
    while(*src != '\0')//src指向的元素不为'\0'时执行,'\0'为结束标志
    {
        *dst++ = *src++;//src所指向元素赋值给dst所指向元素,++进入下一个元素位置
    }
    return dst;//返回dst数组首元素地址
}

3.strncpy()

函数原型:char * strncpy ( char * destination, const char * source, size_t num );
返回的是destination的地址

一般使用

#include <stdio.h>
#include <string.h>

int main()
{
    char arr1[20] = "abcdefhjk";
    char arr2[20] = "lkjhgg";
    char arr3[] = "qwer";
    strncpy(arr1,arr3,4);//将前4个字符复制到arr1中
    strncpy(arr2,arr3,5);//第5个字符为'\0',printf遇'\0'打印结束,arr2变成"qwer\0g"只显示前4个字符
    printf("%s\n",arr1);
    printf("%s\n",arr2);
    return 0;
}

结果如下:
在这里插入图片描述在这里插入图片描述

在这里插入图片描述

4.strcat()

函数原型:char * strcat ( char * destination, const char * source );
返回的是destination的地址
strcat不能给自己追加

一般使用

#include <stdio.h>
#include <string.h>

int main()
{
    char arr[] = "hello ";
    char arr2[] = "world";
    strcat(arr, arr2);
//		my_strcat(arr,arr2);//模拟实现
    printf("%s\n", arr);
    return 0;
}

结果如下:
在这里插入图片描述

模拟实现

char* my_strcat(char* dest, const char* source)//自定义函数
{
    char* ret = dest;//dest首元素地址给指针变量ret
    assert(dest && source);//判断dest和source是否为NULL,有任意一个为NULL则退出,需要引用头文件<assert.h>
    while(*dest != '\0')//解引用,访问当前地址元素,若不为'\0'则执行
    {
        dest++;//进入下一个元素地址
    }
    while (*dest++ = *source++)//从dest'\0'的位置开始将source的元素依次传给dest直到遇到source'\0'的位置
    {
        ;
    }
    return ret;//返回dest起始位置的地址
}

5.strncat()

一般使用

函数原型:char * strncat ( char * destination, const char * source, size_t num );

#include <stdio.h>
#include <string.h>

int main()
{
    char arr1[20] = "hello";
    char arr2[] = "world";
    strncat(arr1,arr2,3);
    printf("%s\n",arr1);
    return 0;
}

结果如下:
在这里插入图片描述

6.strcmp()

函数原型:int strcmp ( const char * str1, const char * str2 );
比较的是两个字符串对应字符的ASCII码值
如果(str1>str2)返回一个(>0)的数
如果(str1=str2)返回一个(=0)的数
如果(str1<str2)返回一个(<0)的数

一般使用

#include <stdio.h>
#include <string.h>

int main()
{
    int ret = strcmp("abc", "abb");
//    int ret = my_strcmp("abc", "abb");//模拟实现
    printf("%d", ret);
    return 0;
}

结果如下:
"abc"最后一个字符‘c’的ASCII值大于"abb"最后一个字符‘b’,返回一个大于0的数字
在这里插入图片描述

模拟实现

int my_strcmp(const char*a, const char*b)
{
    assert(a && b);//判断a和b是否为NULL,有任意一个为NULL则退出,需要引用头文件<assert.h>
    while(*a == *b)//如果对应字符相等执行
    {
        if(*a == '\0')//如果两个数相等则返回0
        {
            return 0;
        }
        a++;//进入a字符串下一个字符的地址
        b++;//进入b字符串下一个字符的地址
    }
    return *a - *b;//返回两个字符ASCII码值相减的结果
}

7.strncmp()

函数原型int strncmp ( const char * str1, const char * str2, size_t num );

一般使用

#include <stdio.h>
#include <string.h>

int main()
{
    char arr1[20] = "abcdef";
    char arr2[20] = "abcqef";
    int ret1 = strncmp(arr1, arr2, 3);
    int ret2 = strncmp(arr1, arr2, 4);
    printf("%d %d",ret1, ret2);
    return 0;
}

结果如下:
在这里插入图片描述

8.strstr()

函数原型:char * strstr ( const char *, const char * );
寻找str2是否在str1中出现,出现则返回地址

一般使用

#include <stdio.h>
#include <string.h>

int main()
{
    char arr1[20] = "abcedefghi";
    char arr2[20] = "defg";
    char * ret = strstr(arr1, arr2);//需要一个指针变量来接收返回的地址
//    char * ret = my_strstr(arr1,arr2);//模拟实现
    if(ret == NULL)
    {
        printf("没有找到");
    }
    else
    {
        printf("%s",ret);//打印字符串
    }
    return 0;
}

结果如下:
在这里插入图片描述

模拟实现

char * my_strstr(const char * str1, const char*str2)
{
    assert(str1 && str2);//判断str1和str2是否为NULL,有任意一个为NULL则退出,需要引用头文件<assert.h>
    const char*s1 = NULL;//设置指针变量s1为空指针
    const char*s2 = NULL;//设置指针变量s2为空指针
    const char*cp = str1;//将str1首元素地址赋给指针变量cp
    if(*str2 == '0')
    {
        return (char*)str1;//如果str2没有元素,直接返回str1的地址
    }
    while(*cp)
    {
        s1 = cp;//将指针变量cp的值赋给指针变量s1
        s2 = str2;//将指针变量str2的值赋给指针变量s2
        while(*s1 && *s2 &&*s1 == *s2)//当s1,s2不为'\0'且s2和s1值相等
        {
            s1++;//进入到s1字符串下一个元素的地址
            s2++;//进入到s2字符串下一个元素的地址       
        }
        if(*s2=='\0')
        {
            return (char*)cp;//如果s2结束返回指针变量cp
        }
        cp++;//进入下一个元素
    }
    return NULL;//找不到则返回NULL
}

在这里插入图片描述

9.strtok()

函数原型:char * strtok ( char * str, const char * delimiters );
如果找到标记delimiters,则指向标记开头的指针

一般使用

#include <stdio.h>
#include <string.h>

int main()
{   
    char arr[] = "abc@qq.com";
    char *p = (char*)"@.";//设置标记
    char temp[20] = {0};
    strcpy(temp, arr);//将arr数组元素复制到temp数组内
    char* ret = NULL; //定义ret为空指针
    //abc\0qq\0com//实质上是把标记字符改为'\0'
    for(ret = strtok(temp,p);ret != NULL;ret = strtok(NULL,p))//循环语句
    {
        printf("%s\n",ret);
    }
    return 0;
}

10.strerror()

函数原型:char * strtok ( char * str, const char * delimiters );
strerror将错误码转换成错误信息,需要printf
此外,可以使用perror()直接打印错误信息(包含了自定义信息),不需要printf

一般使用

#include <stdio.h>
#include <string.h>
#include <error.h>

char * strerror (int errnum);
int main()
{
    FILE *pf = fopen("test.txt", "r");//打开文件
    //0 no error
    if (pf == NULL)//找不到
    {
        printf("%s\n",strerror(errno));//int errno 全局变量返回错误码
        perror("fopen");
        return 1;
    }
    return 0;
}

结果如下:
在这里插入图片描述

11.memcpy()

函数原型:void * memcpy ( void * destination, const void * source, size_t num );
从 source 指定的内存块中复制 num 个字节到 destination 指定的内存块中
返回的是指针变量destination
复制的是字节,需要注意数据类型
不能复制source自身的字符串

一般使用

#include <stdio.h>
#include <string.h>

int main()
{
    int arr1[10] = {1,2,3,4,5,6,7,8,9,10};
    int arr2[10] = {0};
    int i = 0;
    memcpy(arr2, arr1, 20);//20个字节,int类型4个字节一个元素,复制了5个元素
//		my_memcpy(arr2, arr1,20);//模拟实现    
    for(i = 0;i < 10;i++)
    {
        printf("%d",arr2[i]);
    }
    return 0;
}

结果如下:
在这里插入图片描述

模拟实现

void * my_memcpy(void * dst, const void * src, size_t num)
{
    assert(dst && src);//判断dst和src是否为NULL,有任意一个为NULL则退出,需要引用头文件<assert.h>
    void* ret = dst;//void类型指针ret存放dst数组首元素地址
    while(num--)//num不为0时一直递减
    {
        *(char*)dst = *(char*)src;//强制类型转化为char类型,一个字节一个字节访问
        dst = (char*)dst +1;//目标地址进入下一个字节
        src = (char*)src +1;//源地址进入下一个字节
    }
    return ret;
}

12.memmove()

函数原型:void * memmove ( void * destination, const void * source, size_t num );
跟memcpy()不同的地方在于memmove()可以复制source内部的字符串

一般使用

#include <stdio.h>
#include <string.h>

int main()
{
    int i = 0;
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    memmove(arr+4, arr,20);//从arr数组第1个元素开始替换20个字节(5个元素)到arr数组第5个元素
//    my_memmove(arr+4,arr,20);//模拟实现
    for(i = 0;i < 10;i++)
	{
    	printf("%d",arr[i]);
	}
    return 0;
}

结果如下:
在这里插入图片描述

模拟实现

void * my_memmove(void * dst, const void * src, size_t num)
{
    assert(dst && src);//判断dst和src是否为NULL,有任意一个为NULL则退出,需要引用头文件<assert.h>
    void * ret = dst;
    if(dst < src)
    {
        //前->后
        while(num--)
        {
            *(char*)dst = *(char*)src;//强制类型转化为char类型,一个字节一个字节访问
            dst = (char*)dst +1;//目标地址进入下一个字节
            src = (char*)src +1;//源地址进入下一个字节
        }
    }
    else
    {
        //后->前
        while(num--)
        {
            *((char*)dst+num)=*((char*)src+num);
        }
    }
    return ret;
}

原理如下:
在这里插入图片描述

13.memcmp()

函数原型:int memcmp ( const void * ptr1, const void * ptr2, size_t num );
效果跟strcmp()类似
如果(str1>str2)返回一个(>0)的数
如果(str1=str2)返回一个(=0)的数
如果(str1<str2)返回一个(<0)的数

一般使用

#include <stdio.h>
#include <string.h>

int main()
{
    float arr1[] ={1.0,2.0,3.0,4.0};
    float arr2[] ={1.0,3.0,5.0,};
    int ret = memcmp(arr1,arr2,8);//比较两个数组前8个字节的元素
//    int ret = my_memcmp(arr1,arr2,8);//模拟实现
    printf("%d",ret);
    return 0;
}

结果如下:
在这里插入图片描述

模拟实现

int my_memcmp(const void* str1, const void* str2, size_t num)
{
    assert(str1 && str2 && num != 0);//判断str1和str2是否为NULL,num的值不为0,有任意一个为NULL则退出,需要引用头文件<assert.h>
    while(num --)
    {
        if(*(char*)str1 != *(char*)str2)//将str1,str2强制转化为char类型指针,方便一个字节一个字节访问
        {            
            return (*(char*)str1) - (*(char*)str2);//返回差值
        }
        str1 = (char*)str1 +1;//进入下一个字节地址
        str2 = (char*)str2 +1;//进入下一个字节地址
    }
    return 0;//相等返回0
}

14.memset()

函数原型:void * memset ( void * ptr, int value, size_t num );

一般使用

#include <stdio.h>
#include <string.h>

int main()
{
    //arr数组共有40个字节
    int arr[10] = {0};
    int i = 0;
    memset(arr,1,20);//前20个字节设置为1,实际效果为0000000001010101
    for(i = 0;i<10;i++)
    {
        printf("%p\n",arr[i]);
    }
    return 0;
}

结果如下:
在这里插入图片描述

  • 10
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值