likes
comments
collection
share

谈谈String.h头文件里面定义的字符串以及内存函数谈谈String.h头文件中定义的字符串以及内存函数 字符串相关函

作者站长头像
站长
· 阅读数 11

谈谈String.h头文件中定义的字符串以及内存函数

字符串相关函数

strlen(求字符串长度)

size_t strlen(const char* str)
  • '\0'作为结束标志, 返回'\0‘之前的字符个数
  • 返回值类型size_t 是无符号整数(size_t在32位平台下为4个字节,64位平台下为8个字节), 注意如果是返回值直接参与运算的话,不能将size_t类型直接当成整型进行运算,否则可能会出现溢出的情况
#include <stdio.h>
int main()
{
    const char*str1 = "abcdef";
    const char*str2 = "bbb";
    if(strlen(str2)-strlen(str1)>0)
    {
        printf("str2>str1\n");
    }
    else
    {
        printf("srt1>str2\n");
    }
    return 0;
}

最终的输出结果是 str2>str1 因为表达式strlen(str2)-strlen(str1)的结果是一个负数,但在这里要表达为一个无符号整数, 所以结果是一个很大的整数, 那么就会出现结果错误的情况

strcpy(拷贝字符串)

char* strcpy(char * destination, const char * source );
  • 源字符串必须以 '\0' 结束。
  • 会将源字符串中的 '\0' 拷贝到目标空间。(这样才能标志一个字符串)
  • 目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可变。(才能够完成拷贝操作)
  • 是对目标空间的内存进行覆盖操作

strcat(追加字符串)

char * strcat ( char * destination, const char * source );
  • 源字符串必须以 '\0' 结束。(不然无法判断字符串末尾 也就是追加的位置)
  • 目标空间必须有足够的大,能容纳下源字符串的内容。
  • 目标空间必须可修改

注意: 如果字符串自己给自己追加 那么结尾的'\0‘会被覆盖掉,陷入死循环,最好不要自己给自己追加

strcmp(字符串比较)

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

判断大小规则: 一个个字符对应着比较ACSII码值

  • 第一个字符串大于第二个字符串,则返回大于0的数字 一般返回1
  • 第一个字符串等于第二个字符串,则返回0
  • 第一个字符串小于第二个字符串,则返回小于0的数字 一般返回-1

strncpy(字符串拷贝,指定拷贝num个字符)

char * strncpy ( char * destination, const char * source, size_t num );
  • 只拷贝num个字符, 如果source没有那么多个字符, 就直接补'\0',直到num个

strncat(追加指定n个字符)

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

追加完加上'\0‘标志新字符串的结束

strncmp(指定n个字符的比较)

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

比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。

strstr(在字符串里找子串)

char * my_strstr(const char*str1,const char*str2)
{
    char *s1 = str1;
    char *cp = str1;
    char *s2 = str2;

    while(*cp)
    {
        s1 = cp;
        s2 = str2;
        while (*s1&&*s2&&*s1==*s2)
        {
            s1++;
            s2++;
        }
        if(*s2 == '\0')
        {
            return cp;
        }
        cp++;
    }
    return NULL;
}

s1指向母字符串 s2指向子字符串, cp指向母字符串标志此时检验位置

s1从cp(当前检验位置)开始, 逐个移动, s2也同步逐个移动, 如果有不一样的就退出, cp移动到下一个位置, 再次进行检验 s1指向cp s2重新指向str2

谈谈String.h头文件里面定义的字符串以及内存函数谈谈String.h头文件中定义的字符串以及内存函数 字符串相关函

strtok(分割字符串)

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

192.168.110.23 拿出每一段字符 192 168 110 23 类似于Java的spilt 不同的是可以有多个分隔符 sep参数是个字符串,定义了用作分隔符的字符集合

  • 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标 记。
  • strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:
  • strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容 并且可修改。)
  • strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串 中的位置。
  • strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标 记。 如果字符串中不存在更多的标记,则返回 NULL 指针。

调用过程大致如下:

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

int main()
{
    char *p = "1067367579@github.com";
    const char *sep = ".@";
    char arr[30];
    char *str = NULL;
    strcpy(arr, p); // 将数据拷贝一份,处理arr数组的内容
    //第一次要传入目的字符串的起始地址 之后就传入NULL即可 有记忆功能 每次找到下一个分隔符 然后替换为'\0'
    for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep))
    {
        printf("%s\n", str);
    }
}

strerrno(找到错误码对应提示信息的字符串)

char * strerror ( int errnum );

库函数在执行的时候 发生了错误 会错误码存储到一个变量当中 全局变量 然后根据错误码返回相对应的错误信息字符串 变量名为errno, errno每次发生错误的时候都会覆盖

字符分类函数

谈谈String.h头文件里面定义的字符串以及内存函数谈谈String.h头文件中定义的字符串以及内存函数 字符串相关函

内存相关函数(只关注内存中每个字节)

memcpy(指定字节数内存拷贝)

void * memcpy ( void * destination, const void * source, size_t num );
  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置

  • 如果source和destination有任何的重叠,复制的结果都是未定义的(例如 1 2 3 4 5 6 7 8 9 10 如果将前五个元素拷贝到第三个到第七个元素的位置 使用memcpy函数最后结果为1 2 1 2 1 2 1 8 9 10) 原因是拷贝是原地拷贝,在拷贝的过程中如果两个指定的内存范围重叠,那么拷贝的过程中待拷贝的字节也会被拷贝的结果覆盖

memcpy使用void* 类型进行传参 void * 可以接受任意类型的指针

函数内部转化为(char*)类型 这样字节访问与指针运算有效 单位为1个字节 进行操作

//模拟实现memcpy
//memcpy只考虑了对应内存空间没有重叠的情况
void* my_memcpy(void*dest,void*src,size_t num)
{
    while(num--)
    {
        *((char*)dest+num) = *((char*)src+num);
    }
    return dest;
}

memmove(指定字节数内存拷贝,考虑内存重叠)

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

如何实现可能发生重叠的情况下内存拷贝?

改变拷贝的顺序即可 从前向后拷贝 从后向前拷贝

往右移 从后向前拷贝

往左移 从前向后拷贝

dest在src左边 就是向左移

dest在src右边 就是向右移

这个是指指定范围内存有重叠的情况

如果都不存在重叠 那么什么顺序拷贝都可

if dest>src:
   从后向前拷贝
else
   从前向后拷贝

dest大于src且存在内存重叠的情况

谈谈String.h头文件里面定义的字符串以及内存函数谈谈String.h头文件中定义的字符串以及内存函数 字符串相关函

dest小于src且存在内存重叠的情况

谈谈String.h头文件里面定义的字符串以及内存函数谈谈String.h头文件中定义的字符串以及内存函数 字符串相关函

实现:

//模拟实现memmove 需要考虑对应内存区域出现重叠的情况
void* my_memmove(void*dest,void*src,size_t num)
{
    assert(dest&&src);
    //需要判断dest和src的位置关系
    //如果有重叠的区域
    //dest在前面 src在后面 那么需要从前往后拷贝
    //dest在后面 src在前面 那么需要从后往前拷贝
    //为的就是避免src拷贝到后面发现元素已经被之前拷贝移动过去的元素覆盖
    //如果没有重叠区域 那么采取哪种拷贝方式都可以
    if(dest>src)
    {
        //从后往前拷贝
        while(num--)
        {
            *((char*)dest+num) = *((char*)src+num);
        }
    }
    else
    {
        int i=0;
        while(i<num)
        {
            //从前往后拷贝
            *((char*)dest+i) = *((char*)src+i);
        }
    }
    return dest;
}

memcmp(指定内存字节比较)

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

就是在内存里面比较每个字节的大小

memset(设定指定字节的内容)

void* memset(void* ptr, int value, size_t num) 

ptr前num个字节都设置为value (以字节为单位进行设置)

转载自:https://juejin.cn/post/7401403660246220854
评论
请登录