1. 字符串以’\0’为结束标志,strlen函数返回的是’\0’前的字符个数,不包括’\0′

  1. 参数的指向的字符串必须是’\0’为结束标志,不然结果不确定

  1. 函数的返回类型是size_t(无符号的整型)

strlen的使用

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

int main()
{
    char arr1[] = "hello world!";

    size_t ret = strlen(arr1);

    printf("%u", ret);

    return 0;
}

strlen的模拟使用

#include <stdio.h>

int my_strlen(char* p)
{
    int sz = 0;
    while (*p)
    {
        p++;
        sz++;
    }
    return sz;
}

int main()
{
    char arr[] = "abcde";
    int sz=my_strlen(arr);
    printf("%d\n", sz);
    return 0;
}

易错点strlen的返回值是size_t

eg

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

int main()
{
    const char* str1 = "abcdef";
    const char* str2 = "abc";
    if (strlen(str2) - strlen(str1) > 0)
    {
        printf("str2>str1");
    }
    else
    {
        printf("str1>str2");
    }

    return 0;
}

stlen(str2)返回3,strlen(str1)返回6,3-6=-3,但是-3是无符号数>0,所以if里面的条件是真的

strcpy函数

  1. 原字符串必须以’\0’结束

  1. 会将原字符串的”\0’拷贝到目标空间

  1. 目标空间必须足够大,以确保可以存放源字符串

  1. 目标空间必须可变

  1. 学会模拟实现

strcpy的使用

#include <stdio.h>
#include <string.h>
int main()
{
    char arr1[100] = "123456789";
    char arr2[10] = "abcdef";
    strcpy(arr1, arr2);
    puts(arr1);

    return 0;
}

将arr2复制到arr1,覆盖了arr1原本的内容

strcpy的模拟实现

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

void my_strcpy(char* arr1, char* arr2)
{
    while (*arr2)
    {
        *arr1 = *arr2;
        arr1++;
        arr2++;
    }
    *arr1 = *arr2;
}
int main()
{
    char arr1[100] = "123456789";
    char arr2[10] = "abcdef";
    my_strcpy(arr1, arr2);
    puts(arr1);
    return 0;
}

strcat函数

  1. 源字符串必须以’\0’结束

  1. 目标空间必须足够大,能容纳下源字符串的内容

  1. 目标空间必须可以修改

  1. 字符串自己给自己追加,如何

strcat的实现

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

int main()
{
    char arr1[100] = "12345";
    char arr2[10] = "6789";
    strcat(arr1, arr2);
    puts(arr1);

    return 0;
}

strcat函数的模拟实现

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

void my_strcat(char* arr1, char* arr2)
{
    while (*arr2)
    {
        if (*arr1 == '\0')
        {
            *arr1 = *arr2;
            arr2++;
        }
        arr1++;
    }
    arr1 = arr2;
}

int main()
{
    char arr1[100] = "12345";
    char arr2[10] = "6789";
    my_strcat(arr1, arr2);
    puts(arr1);

    return 0;
}

自己给自己追加会发生什么

说明自己给自己追加是行不通的

strcmp函数

标准规定:

  1. 第一个字符串大于第二个字符串,则返回大于0的数字

  1. 第一个字符串等于第二个字符串,则返回0

  1. 第一个字符串小于第二个字符串,则返回小于0的数字

sttrcmp函数的实现

#include <stdio.h>

int main()
{
    char arr1[] = "abcd";
    char arr2[] = "abaa";
    int val = strcmp(arr1, arr2);
    printf("%d\n", val);

    return 0;
}

比较的是每一位字符对应的ASCII码值,c的ASCII码值大于a的,所以我们返回一个大于0的数字

strcmp的模拟实现

#include <stdio.h>

int my_strcmp(const char* arr1, const char* arr2)
{
    while (*arr1 != '\0' || *arr2 != '\0')
    {
        if (*arr1 > *arr2)
        {
            return 1;
        }
        if (*arr1 < *arr2)
        {
            return -1;
        }
        arr1++;
        arr2++;
    }
    return 0;
}

int main()
{
    char arr1[] = "abcd";
    char arr2[] = "abdd";
    int val = my_strcmp(arr1, arr2);
    printf("%d\n", val);

    return 0;
}

strncpy函数

  1. 拷贝num个字符从源字符到目标空间

  1. 如果源字符串长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个

strncpy函数的实现

#include <stdio.h>
#include <string.h>
int main()
{
    char arr1[100] = "abcdefghijklnm";
    char arr2[100] = "123456789";
    strncpy(arr1, arr2, 5);
    printf("%s\n", arr1);
    return 0;
}

对比strcpy与strncpy

发现strcpy是将arr2的全部放到arr1,arr1原来的字符不见了

strncpy是将num个字符从第1个字符开始从arr1开始替代,没有替代的字符不改变,而strcpy替代后,后面的字符变成了0

strncpy函数的模拟

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

void my_strncpy(char* arr1, char* arr2, size_t num)
{
    while(num)
    { 
        *arr1 = *arr2;
        arr1++;
        arr2++;
        num--;
    }
}

int main()
{
    char arr1[100] = "abcdefgh";
    char arr2[100] = "123456789";
    my_strncpy(arr1, arr2, 5);
    printf("%s\n", arr1);
    return 0;
}

strncat函数

strncat的实现

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

int main()
{
    char arr1[100] = "12345";
    char arr2[100] = "abcdefg";
    strncat(arr1, arr2, 3);
    printf("%s\n",arr1);

    return 0;
}

strncat与strcat的区别

strcat是将arr2全部的字符追加到arr1后面。strncat是将arr2里面num个字符追加到arr1

strncat的模拟实现

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

void my_strncat(char* arr1,char* arr2,size_t num)
{
    while (num)
    {
        if (*arr1 == '\0')
        {
            *arr1 = *arr2;
            arr2++;
            num--;
        }
        arr1++;
    }
}
int main()
{
    char arr1[100] = "12345";
    char arr2[100] = "abcdefg";
    my_strncat(arr1, arr2, 3);
    printf("%s\n",arr1);

    return 0;
}

strncmp函数

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

strncmp的实现

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

int main()
{
    const char* arr1 = "abcdefg";
    const char* arr2 = "abab";
    int val=strncmp(arr1, arr2, 4);
    printf("%d\n", val);

    return 0;
}

strcmp与strncmp的区别

比较法则strncmp与strcmp一样,都是比较ASCII码,strcmp的比较,如果得不到结果,一直比较到最后一个字符,而strncmp比较字符,只比较到num个就结束了。

strncmp的模拟实现

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

int my_strncmp(const char* arr1, const char* arr2, size_t num)
{
    while (num)
    {
        if (*arr1 > *arr2)
        {
            return 1;
        }
        if (*arr1 < *arr2)
        {
            return -1;
        }
        arr1++;
        arr2++;
        num--;
    }
    return 0;
}

int main()
{
    const char* arr1 = "abadefg";
    const char* arr2 = "abcb";
    int val=my_strncmp(arr1, arr2, 4);
    printf("%d\n", val);

    return 0;
}

strstr函数

strstr函数的实现


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

int main()
{
    char arr1[] = "123abc456efg";
    char arr2[] = "abc";
    char* ret = NULL;
    ret = strstr(arr1, arr2);
    puts(ret);
    return 0;
}

在字符串arr1中查找字符串arr2,查到后返回查到字符串的首地址

如果查不到呢

返回一个空指针

strstr模拟实现

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

char* my_strstr(const char* arr1, const char* arr2)
{
    char* s1 = NULL;
    char* s2 = NULL;
    char* pc = arr1;
    while (*pc)
    {
        s1 = pc;
        s2 = arr2;
        while (*s1 && *s2 && * s1 == *s2)
        {
            s1++;
            s2++;
        }
        if (*s2 == '\0')
        {
            return pc;
        }
        pc++;
    }
    return NULL;
}

int main()
{
    char arr1[] = "abcdefabcdef";
    char arr2[] = "def";
    char* ret = NULL;
    ret = my_strstr(arr1, arr2);
    if (ret != NULL)
    {
        puts(ret);
    }
    
    return 0;
}

strchr函数

strchr函数的实现

#include <stdio.h>
#include <string.h>
int main()
{
    const char* arr = "abcdefg";
    const char ch = 'c';
    char* tmp = NULL;
    tmp = strchr(arr, ch);
    puts(tmp);
    return 0;
}

在字符串arr中查找字符’c’,返回字符串arr中c的地址

strchr模拟实现

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

char* my_strchr(const char* arr, const char ch)
{
    while (*arr)
    {
        if (*arr == ch)
        {
            return arr;
        }
        arr++;
    }
    return NULL;
}

int main()
{
    const char* arr = "abcdefg";
    const char ch = 'c';
    char* tmp = NULL;
    tmp = my_strchr(arr, ch);
    puts(tmp);
    return 0;
}

strtok函数

  1. delimited参数是个字符串,定义了用作分隔符的字符集合

  1. strtok函数找到str中的下一个标记,并将其用’\0’结尾,返回一个指向这个标记的指针.(注:strtok函数会改变操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)

  1. strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存其在字符串中的位置

  1. strtok函数的第一个参数为NULL,函数将在同一个字符串被保存的位置开始,查找下一个标记

  1. 如果字符串不存在更多的标记,则返回NULL指针

strtok函数的实现

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

int main()
{
    char* p = "1186888586@qq.com";
    const char* delimited = "@.";
    char* str = NULL;
    char arr[100] = {'0'};
    strcpy(arr, p);
    for (str = strtok(arr, delimited); str != NULL; str = strtok(NULL, delimited))
    {
        puts(str);
    }

    return 0;
}

利用·strcpy拷贝一份我们要用来查到的字符串

查到了返回查到之前起始位置的地址,将查到的字符置为’\0′

查不到返回一个空指针

查到后,下一次查找,第一个参数使用空指针

strerror函数

strerror函数的实现

#include <stdio.h>
#include <errno.h>
int main()
{
    FILE* pf = NULL;
    pf = fopen("test.txt", "r");
    if (NULL == pf)
    {
        printf("%s\n", strerror(errno));
    }
    return 0;
}

通常我们打印错误信息还可以使用perror函数

#include <stdio.h>
#include <errno.h>
int main()
{
    FILE* pf = NULL;
    pf = fopen("test.txt", "r");
    if (NULL == pf)
    {
        perror("fopen:");
    }
    return 0;
}

memcpy函数

  1. 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存

  1. 这个函数在遇到’\0’的时候并不会停下来

  1. 如果source和destination有任何的重叠,复制的结果都是未定义的

#include <stdio.h>
#include <string.h>
int main()
{
    int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int arr2[10] = { 11,12,13,14,15,16,17,18,19,20 };
    memcpy(arr1, arr2, 20);
    for (int i = 0; i < sizeof(arr1) / sizeof(arr1[0]); i++)
    {
        printf("%d ", arr1[i]);
    }

    return 0;
}

将arr2内的20个字节复制到arr1中

memcpy一般不做重叠的拷贝,即自己给自己拷贝

strcpy只能拷贝字符,memcpy可以拷贝所以类型的元素

memcpy函数的模拟

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

void* my_memcpy(void* arr1, const void* arr2, size_t num)
{
    void* tmp = arr1;
    while (num)
    {
        *(char*)arr1 = *(char*)arr2;
        arr1 = (char*)arr1 + 1;
        arr2 = (char*)arr2 + 1;
        num--;
    }
    return tmp;
}

int main()
{
    int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int arr2[10] = { 11,12,13,14,15,16,17,18,19,20 };
    my_memcpy(arr1, arr2, 20);
    for (int i = 0; i < sizeof(arr1) / sizeof(arr1[0]); i++)
    {
        printf("%d ", arr1[i]);
    }

    return 0;
}

自身拷贝推荐使用memmove函数,在vs中memcpy函数的设计与memmove一样,但是在其他平台我们不能保证,所以我们拷贝时可以统一使用memmove函数

memmove函数

  1. 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的

  1. 如果源空间和目标空间出现重叠,就是使用memmove函数处理

memmove函数的实现

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

int main()
{
    int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int arr2[10] = { 11,12,13,14,15,16,17,18,19,20 };
    memmove(arr1, arr1 + 2, 20);
    for (int i = 0; i < sizeof(arr1) / sizeof(arr1[0]); i++)
    {
        printf("%d ", arr1[i]);
    }

    return 0;
}

memmove的模拟实现

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

void* my_memmove(void* dest, void* src, size_t num)
{
    void* tmp = dest;
    if (*(char*)dest < *(char*)src)
    {
        while (num)
        {
            *(char*)dest = *(char*)src;
            dest = (char*)dest + 1;
            src = (char*)src + 1;
            num--;
        }
    }
    else
    {
        while (num)
        {
            *((char*)dest+num) = *((char*)src+num);
            num--;
        }
        *((char*)dest + num) = *((char*)src + num);
    }
    return tmp;
}

int main()
{
    int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int arr2[10] = { 11,12,13,14,15,16,17,18,19,20 };
    my_memmove(arr1+2, arr1 , 20);
    for (int i = 0; i < sizeof(arr1) / sizeof(arr1[0]); i++)
    {
        printf("%d ", arr1[i]);
    }

    return 0;
}

memcmp函数

比较从ptr1和ptr2指针开始的num个字节

memcmp的实现

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

int main()
{
    const char* p1 = "abcd";
    const char* p2 = "abad";
    printf("%d\n", memcmp(p1, p2, 4));
    int arr1[] = { 1,2,3,4 };
    int arr2[] = { 1,2,3,5 };
    printf("%d\n", memcmp(arr1, arr2, 16));
    return 0;
}

strcmp函数可以比较字符串,memcmp可以比较内存中所以类型的元素

memset函数

memset函数的实现

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

int main()
{
    char arr[] = "hello world!";
    memset(arr, '*', 5);
    puts(arr);
    return 0;
}

将arr1字符串的5个字节置为’*’

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

int main()
{
    int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
    memset(arr, 1, 40);
    return 0;
}

memset可以将10个元素置为1吗

memset是按字节处理,每一个直接都置为1,int类型占4个字节明显它不能将10个元素置为1


版权声明:本文为m0_73850645原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/m0_73850645/article/details/128676678