自学内容网 自学内容网

模拟实现C库函数~

上篇文章介绍完了C语言中一些常用的库函数,现在咱们也可以运用自己所学知识模拟实现相同功能属于咱们自己的库函数。那咱们就开始吧@

1.模拟实现strlen函数

要模拟实现 strlen 函数,我们需要编写一个函数来计算一个以空字符 \0 结尾的字符串的长度。这个函数将遍历字符串中的每个字符,直到遇到空字符 \0,然后返回遍历的字符数量。

以下是模拟实现 strlen 函数的示例代码:

#include <stdio.h>

// 模拟实现 strlen 函数
size_t my_strlen(const char *str) 
{
    const char *ptr = str; // 指向字符串的指针
    size_t length = 0;     // 字符串的长度

    // 遍历字符串直到遇到空字符
    while (*ptr != '\0') 
   {
        length++; // 增加长度计数
        ptr++;    // 移动指针到下一个字符
    }

    return length; // 返回字符串的长度
}

int main()
 {
    const char str[] = "Hello, World!";
    size_t length = my_strlen(str);
    printf("The length of the string is: %zu\n", length);
    return 0;
}

代码说明:

  1. 函数定义my_strlen 函数接受一个指向字符串的指针 str 作为参数。
  2. 指针遍历:使用一个指针 ptr 遍历字符串,直到遇到空字符 \0
  3. 长度计算:使用变量 length 记录字符串的长度。
  4. 返回值:函数返回字符串的长度。

这个模拟实现的 my_strlen 函数在功能上与标准库中的 strlen 函数相同,它正确地计算了字符串的长度,并且没有使用任何额外的库函数。这种方法的时间复杂度是 O(n),其中 n 是字符串的长度。

 

2.模拟实现strcpy 函数

  

要模拟实现 strcpy 函数,我们需要编写一个函数来将源字符串(包括空字符 \0)复制到目标字符串中。这个函数将逐字节复制字符,直到遇到源字符串的空字符 \0

以下是模拟实现 strcpy 函数的示例代码:

#include <stdio.h>

// 模拟实现 strcpy 函数
char *my_strcpy(char *dest, const char *src) 
{
    char *start = dest; // 保存目标字符串的起始地址

    // 遍历字符串直到遇到空字符
    while ((*dest++ = *src++) != '\0') 
    {
        // 循环体为空,因为所有的工作都在循环条件中完成了
    }

    return start; // 返回目标字符串的起始地址
}

int main() 
{
    char src[] = "Hello, World!";
    char dest[20]; // 确保目标数组足够大以存储 src 字符串

    // 使用模拟的 strcpy 函数复制字符串
    my_strcpy(dest, src);

    printf("Copied string: %s\n", dest);

    return 0;
}

代码说明:

  1. 函数定义my_strcpy 函数接受两个参数:目标字符串 dest 和源字符串 src
  2. 指针遍历:使用 while 循环逐字节复制字符,直到遇到源字符串的空字符 \0
  3. 返回值:函数返回目标字符串的起始地址。

这个模拟实现的 my_strcpy 函数在功能上与标准库中的 strcpy 函数相同,它正确地复制了字符串,包括空终止符。这种方法的时间复杂度是 O(n),其中 n 是字符串的长度。

请注意,在使用 my_strcpy 函数时,必须确保目标字符串 dest 有足够的空间来存储源字符串 src,包括空终止符。如果目标空间不足,可能会导致缓冲区溢出,这是潜在的安全风险。在实际应用中,推荐使用 strncpy 或其他更安全的字符串操作函数。

3.模拟实现strcat函数

  

要模拟实现 strcat 函数,我们需要编写一个函数来将源字符串追加到目标字符串的末尾,并确保结果字符串以空字符 \0 结尾。这个函数将从目标字符串的末尾开始复制源字符串的每个字符,直到遇到源字符串的空字符 \0

以下是模拟实现 strcat 函数的示例代码:

#include <stdio.h>

// 模拟实现 strcat 函数
char *my_strcat(char *dest, const char *src)
 {
    char *end = dest; // 指向目标字符串末尾的指针

    // 找到目标字符串的末尾
    while (*end != '\0') 
{
        end++;
    }

    // 复制源字符串到目标字符串的末尾
    while (*src != '\0')
 {
        *end = *src;
        src++;
        end++;
    }

    // 添加空字符以确保字符串正确结束
    *end = '\0';

    return dest; // 返回目标字符串的起始地址
}

int main()
 {
    char dest[20] = "Hello, ";
    char src[] = "World!";

    // 使用模拟的 strcat 函数追加字符串
    my_strcat(dest, src);

    printf("Concatenated string: %s\n", dest);

    return 0;
}

代码说明:

  1. 函数定义my_strcat 函数接受两个参数:目标字符串 dest 和源字符串 src
  2. 找到目标字符串末尾:使用一个 while 循环找到目标字符串的末尾。
  3. 复制源字符串:使用另一个 while 循环将源字符串的每个字符复制到目标字符串的末尾。
  4. 添加空字符:在复制完成后,添加空字符 \0 以确保字符串正确结束。
  5. 返回值:函数返回目标字符串的起始地址。

这个模拟实现的 my_strcat 函数在功能上与标准库中的 strcat 函数相同,它正确地追加了字符串,并确保结果字符串以空字符结尾。这种方法的时间复杂度是 O(n + m),其中 n 是目标字符串的长度,m 是源字符串的长度。

请注意,在使用 my_strcat 函数时,必须确保目标字符串 dest 有足够的空间来存储两个字符串的连接结果,包括空终止符。如果目标空间不足,可能会导致缓冲区溢出,这是潜在的安全风险。在实际应用中,推荐使用 strncat 或其他更安全的字符串操作函数。

4.模拟实现strcmp函数

  

要模拟实现 strcmp 函数,我们需要编写一个函数来比较两个字符串,并根据字典顺序返回它们的关系。strcmp 函数会逐字符比较两个字符串,直到找到不相等的字符或遇到空字符 \0

以下是模拟实现 strcmp 函数的示例代码:

#include <stdio.h>

// 模拟实现 strcmp 函数
int my_strcmp(const char *str1, const char *str2) 
{
    // 同时遍历两个字符串,直到找到不相等的字符或空字符
    while (*str1 != '\0' && *str1 == *str2) 
   {
        str1++;
        str2++;
    }

    // 返回两个字符的差值,如果相等则为 0
    return (unsigned char)*str1 - (unsigned char)*str2;
}

int main() 
{
    const char str1[] = "Hello";
    const char str2[] = "World";
    const char str3[] = "Hello";

    printf("str1 vs str2: %d\n", my_strcmp(str1, str2)); // 应该输出负数,因为 'H' < 'W'
    printf("str1 vs str3: %d\n", my_strcmp(str1, str3)); // 应该输出 0,因为字符串相等

    return 0;
}

代码说明:

  1. 函数定义my_strcmp 函数接受两个指向字符串的指针 str1 和 str2 作为参数。
  2. 字符比较:使用 while 循环同时遍历两个字符串,比较对应的字符。如果当前位置的字符相等,则继续比较下一个字符。
  3. 返回结果:如果遇到不相等的字符,则返回它们的差值。如果 str1 中的字符小于 str2 中的字符,则返回负数;如果 str1 中的字符大于 str2 中的字符,则返回正数。如果所有字符都相等,直到遇到空字符,则返回 0。
  4. 类型转换:使用 (unsigned char) 类型转换确保比较时的符号扩展不会影响结果。

这个模拟实现的 my_strcmp 函数在功能上与标准库中的 strcmp 函数相同,它正确地比较了两个字符串,并根据字典顺序返回了它们的关系。这种方法的时间复杂度是 O(n),其中 n 是两个字符串中较短字符串的长度。

5.模拟实现strncmp函数

  

要模拟实现 strncmp 函数,我们需要编写一个函数来比较两个字符串的前 n 个字符,并根据字典顺序返回它们的关系。strncmp 函数会逐字符比较两个字符串,直到找到不相等的字符、遇到空字符 \0 或比较了 n 个字符。

以下是模拟实现 strncmp 函数的示例代码:

#include <stdio.h>

// 模拟实现 strncmp 函数
int my_strncmp(const char *str1, const char *str2, size_t n) 
{    
    // 同时遍历两个字符串,直到找到不相等的字符、空字符或比较了 n 个字符
    while (n-- > 0 && *str1 != '\0' && *str1 == *str2) 
    {
        str1++;

        str2++;
    }

    // 如果在比较的字符数内找到了不相等的字符,返回它们的差值
    // 如果比较的字符数达到了 n,返回 0
    return (n == 0) ? 0 : (unsigned char)*str1 - (unsigned char)*str2;
}

int main() 
{
    const char str1[] = "Hello";
    const char str2[] = "World";
    const char str3[] = "Hell";

    printf("str1 vs str2 (3): %d\n", my_strncmp(str1, str2, 3)); 
// 应该输出 0,因为 "Hel" == "Wor"
    printf("str1 vs str3 (4): %d\n", my_strncmp(str1, str3, 4)); 
// 应该输出正数,因为 "Hell" > "Hell"
    printf("str1 vs str3 (5): %d\n", my_strncmp(str1, str3, 5)); 
// 应该输出 0,因为 "Hello" == "Hell"

    return 0;
}

代码说明:

  1. 函数定义my_strncmp 函数接受三个参数:两个指向字符串的指针 str1 和 str2,以及最大比较字符数 n
  2. 字符比较:使用 while 循环同时遍历两个字符串,比较对应的字符。如果当前位置的字符相等,并且还有剩余的字符可以比较(n-- > 0),则继续比较下一个字符。
  3. 返回结果:如果比较的字符数达到了 n,则返回 0。如果找到了不相等的字符,则返回它们的差值。如果 str1 中的字符小于 str2 中的字符,则返回负数;如果 str1 中的字符大于 str2 中的字符,则返回正数。
  4. 类型转换:使用 (unsigned char) 类型转换确保比较时的符号扩展不会影响结果。

这个模拟实现的 my_strncmp 函数在功能上与标准库中的 strncmp 函数相同,它正确地比较了两个字符串的前 n 个字符,并根据字典顺序返回了它们的关系。这种方法的时间复杂度是 O(n),其中 n 是最大比较字符数。

6.模拟实现strncpy函数

  

要模拟实现 strncpy 函数,我们需要编写一个函数来将源字符串复制到目标字符串,但最多复制指定数量的字符,并确保目标字符串以空字符 \0 结尾。如果源字符串的长度小于指定的数量,目标字符串将用空字符填充至指定长度。

以下是模拟实现 strncpy 函数的示例代码:

#include <stdio.h>
#include <string.h> // 包含 strlen 函数的头文件

// 模拟实现 strncpy 函数
char *my_strncpy(char *dest, const char *src, size_t n) 
{
    char *start = dest; // 保存目标字符串的起始地址

    // 复制每个字符,直到遇到源字符串的结束或达到 n
    while (n-- > 0 && *src != '\0') {
        *dest++ = *src++;
    }

    // 如果源字符串长度小于 n,用空字符填充剩余部分
    while (n-- > 0) {
        *dest++ = '\0';
    }

    return start; // 返回目标字符串的起始地址
}

int main() 
{
    char src[] = "Hello, World!";
    char dest[20]; // 确保目标数组足够大以存储 src 字符串

    // 使用模拟的 strncpy 函数复制字符串,最多复制 13 个字符
    my_strncpy(dest, src, 13);

    printf("Copied string: %s\n", dest);

    return 0;
}

代码说明:

  1. 函数定义my_strncpy 函数接受三个参数:目标字符串 dest、源字符串 src 和最大复制字符数 n
  2. 复制字符:使用 while 循环复制每个字符,直到遇到源字符串的结束或达到 n
  3. 填充空字符:如果源字符串长度小于 n,使用另一个 while 循环用空字符填充目标字符串的剩余部分。
  4. 返回值:函数返回目标字符串的起始地址。

这个模拟实现的 my_strncpy 函数在功能上与标准库中的 strncpy 函数相同,它正确地复制了字符串,并确保目标字符串以空字符结尾。这种方法的时间复杂度是 O(n),其中 n 是最大复制字符数。

请注意,在使用 my_strncpy 函数时,必须确保目标字符串 dest 有足够的空间来存储两个字符串的连接结果,包括空终止符。如果目标空间不足,可能会导致缓冲区溢出,这是潜在的安全风险。在实际应用中,推荐使用 strncpy 或其他更安全的字符串操作函数。

7.模拟实现strncat函数

  

要模拟实现 strncat 函数,我们需要编写一个函数来将源字符串追加到目标字符串的末尾,但最多追加指定数量的字符,并确保结果字符串以空字符 \0 结尾。如果源字符串的长度小于指定的数量,结果字符串将包含源字符串的所有字符。

以下是模拟实现 strncat 函数的示例代码:

#include <stdio.h>

// 模拟实现 strncat 函数
char *my_strncat(char *dest, const char *src, size_t n)
 {
    char *end = dest; // 指向目标字符串末尾的指针

    // 找到目标字符串的末尾
    while (*end != '\0') {
        end++;
    }

    // 复制每个字符,直到遇到源字符串的结束或达到 n
    while (n-- > 0 && *src != '\0') 
    {
        *end = *src;
        src++;
        end++;
    }

    // 添加空字符以确保字符串正确结束
    *end = '\0';

    return dest; // 返回目标字符串的起始地址
}

int main() 
{
    char dest[20] = "Hello, ";
    const char *src = "World!";
    size_t n = 13; // 指定追加的最大字符数

    // 使用模拟的 strncat 函数追加字符串
    my_strncat(dest, src, n);

    printf("Concatenated string: %s\n", dest);

    return 0;
}

代码说明:

  1. 函数定义my_strncat 函数接受三个参数:目标字符串 dest、源字符串 src 和最大追加字符数 n
  2. 找到目标字符串末尾:使用 while 循环找到目标字符串的末尾。
  3. 复制字符:使用另一个 while 循环将源字符串的每个字符复制到目标字符串的末尾,直到遇到源字符串的结束或达到 n
  4. 添加空字符:在目标字符串的末尾添加空字符 \0,确保字符串正确结束。
  5. 返回值:函数返回目标字符串的起始地址。

这个模拟实现的 my_strncat 函数在功能上与标准库中的 strncat 函数相同,它正确地追加了字符串,并确保结果字符串以空字符结尾。这种方法的时间复杂度是 O(m+n),其中 m 是目标字符串的长度,n 是最大追加字符数。

请注意,在使用 my_strncat 函数时,必须确保目标字符串 dest 有足够的空间来存储两个字符串的连接结果,包括空终止符。如果目标空间不足,可能会导致缓冲区溢出,这是潜在的安全风险。在实际应用中,推荐使用 strncat 或其他更安全的字符串操作函数。

8.模拟实现strstr函数

  

要模拟实现 strstr 函数,我们需要编写一个函数来在一个字符串中查找第一次出现的另一个字符串,并返回第一次出现的位置。如果找不到子字符串,则返回 NULL

以下是模拟实现 strstr 函数的示例代码:

#include <stdio.h>

// 模拟实现 strstr 函数
char *my_strstr(const char *haystack, const char *needle) 
{
    if (*needle == '\0') 
{
        return (char *)haystack; // 如果 needle 是空字符串,返回 haystack 的起始地址
    }

    const char *h = haystack;
    const char *n = needle;

    while (*h) 
{
        const char *h_temp = h;
        const char *n_temp = n;

        // 检查 haystack 中的当前位置是否与 needle 匹配
        while (*n_temp && *h_temp == *n_temp) 
        {
            h_temp++;
            n_temp++;
        }

        // 如果找到匹配的子字符串,返回匹配的起始地址
        if (*n_temp == '\0') {
            return (char *)h;
        }

        // 移动到 haystack 的下一个字符
        h++;
    }

    return NULL; // 如果没有找到匹配的子字符串,返回 NULL
}

int main()
 {
    const char haystack[] = "Hello, World! Welcome to the world of C.";
    const char needle1[] = "World";
    const char needle2[] = "C++";

    char *result1 = my_strstr(haystack, needle1);
    char *result2 = my_strstr(haystack, needle2);

    if (result1 != NULL) 
    {
        printf("'%s' found in '%s' at position %ld\n", needle1, haystack, result1 - haystack);
    } else 
    {
        printf("'%s' not found in '%s'\n", needle1, haystack);
    }

    if (result2 != NULL)
     {
        printf("'%s' found in '%s' at position %ld\n", needle2, haystack, result2 - haystack);
    } else 
    {
        printf("'%s' not found in '%s'\n", needle2, haystack);
    }

    return 0;
}

代码说明:

  1. 函数定义my_strstr 函数接受两个参数:主字符串 haystack 和要查找的子字符串 needle
  2. 空字符串处理:如果 needle 是空字符串,返回 haystack 的起始地址。
  3. 查找子字符串:使用两个 while 循环在 haystack 中查找 needle 的第一次出现。内部循环检查当前位置是否与 needle 匹配。
  4. 返回结果:如果找到匹配的子字符串,返回匹配的起始地址;如果没有找到,返回 NULL

这个模拟实现的 my_strstr 函数在功能上与标准库中的 strstr 函数相同,它正确地查找子字符串并返回第一次出现的位置。这种方法的时间复杂度是 O(m*n),其中 m 是 haystack 的长度,n 是 needle 的长度。

请注意,在使用 my_strstr 函数时,必须确保 haystackneedle 都是有效的 C 字符串(以 \0 结尾)。如果 needle 不是有效的 C 字符串,可能会导致未定义行为。在实际应用中,推荐使用 strstr 或其他更安全的字符串操作函数。

9.模拟实现strtok函数

要模拟实现 strtok 函数,我们需要编写一个函数来根据分隔符分割字符串,并返回下一个分割后的子字符串。strtok 函数是可重入的,它使用静态缓冲区来保存当前的分割位置。

以下是模拟实现 strtok 函数的示例代码:

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

// 静态变量,保存上次分割的位置
static char *g_strtok_pos = NULL;

// 模拟实现 strtok 函数
char *my_strtok(char *str, const char *delim)
 {
    // 如果 str 为 NULL,则继续从上次的位置开始分割
    if (str == NULL)
     {
        str = g_strtok_pos;
    } else {
        // 重置静态变量,从新的字符串开始分割
        g_strtok_pos = str;
    }

    // 跳过分隔符
    while (*str != '\0' && strchr(delim, *str)) 
    {
            str++;
            }

    // 如果到达字符串末尾,返回 NULL
    if (*str == '\0') 
        {
        return NULL;
        }

    // 找到子字符串的开始位置
    char *token = str;

    // 跳过非分隔符的字符
    while (*str != '\0' && !strchr(delim, *str)) 
              {
                str++;
               }

    // 如果找到了分隔符,将其替换为 '\0',并保存下次分割的位置
    if (*str != '\0') 
    {
        *str = '\0';
        g_strtok_pos = str + 1;
    } else
     {
        // 如果到达字符串末尾,设置静态变量为 NULL
        g_strtok_pos = NULL;
    }

    return token; // 返回子字符串
}

int main()
{
    char str[] = "Hello, World! This is a test.";
    const char delim[] = " ,!";
    char *token;

    // 使用模拟的 strtok 函数分割字符串
    while ((token = my_strtok(str, delim)) != NULL)
     {
        printf("%s\n", token);
        str += strlen(token) + 1; // 更新 str 指针,跳过已处理的部分
    }

    return 0;
}

代码说明:

  1. 静态变量:使用一个静态变量 g_strtok_pos 保存上次分割的位置。
  2. 分割字符串:如果 str 为 NULL,则继续从上次的位置开始分割;否则,重置静态变量,从新的字符串开始分割。
  3. 跳过分隔符:使用 while 循环跳过分隔符。
  4. 找到子字符串:找到子字符串的开始位置,并跳过非分隔符的字符。
  5. 替换分隔符:如果找到了分隔符,将其替换为 \0,并保存下次分割的位置。
  6. 返回结果:返回子字符串的指针。

这个模拟实现的 my_strtok 函数在功能上与标准库中的 strtok 函数相同,它正确地分割字符串并返回下一个分割后的子字符串。这种方法的时间复杂度是 O(n),其中 n 是字符串的长度。

请注意,这个实现不是线程安全的,因为它使用了静态变量来保存状态。在多线程环境中,应使用线程安全的替代函数,如 strtok_r

10.模拟实现strerror函数

  

模拟实现 strerror 函数需要一个机制来将错误码映射到它们对应的错误消息。在标准库中,strerror 函数使用一个内部的错误码到错误消息的映射表。为了简化,我们可以创建一个固定的错误码和错误消息的映射表,并提供一个函数来查找并返回相应的错误消息。

以下是模拟实现 strerror 函数的示例代码:

#include <stdio.h>

// 定义一个结构体来映射错误码和错误消息
typedef struct 
{
    int errnum;
    const char *errmsg;
} ErrEntry;

// 创建一个错误码到错误消息的映射表
static ErrEntry errtab[] =
 {
    {0, "Success"},
    {1, "Unknown error"},
    {2, "Invalid argument"},
    // ... 可以添加更多的错误码和错误消息
};

// 模拟实现 strerror 函数
const char *my_strerror(int errnum) 
{
    // 在映射表中查找错误码
    for (int i = 0; i < sizeof(errtab) / sizeof(errtab[0]); i++) 
       {
        if (errtab[i].errnum == errnum) 
        {
            return errtab[i].errmsg;
        }
    }
    // 如果没有找到,返回一个默认的错误消息
    return "Unknown error";
}

int main()
 {
    int errnum = 2;
    const char *errmsg = my_strerror(errnum);
    printf("Error %d: %s\n", errnum, errmsg);

    return 0;
}

代码说明:

  1. 错误码和错误消息映射表:使用一个 ErrEntry 结构体数组 errtab 来存储错误码和对应的错误消息。
  2. 模拟 strerror 函数my_strerror 函数接受一个错误码 errnum 作为参数,并在映射表中查找对应的错误消息。
  3. 查找和返回:如果找到对应的错误消息,则返回它;如果没有找到,则返回一个默认的错误消息。

这个模拟实现的 my_strerror 函数提供了一个基本的错误码到错误消息的映射,类似于标准库中的 strerror 函数。这种方法的时间复杂度是 O(n),其中 n 是映射表中条目的数量。在实际应用中,可能需要一个更复杂的数据结构(如哈希表)来提高查找效率,特别是当错误码数量很多时。

11.模拟实现memcpy函数

  

模拟实现 memcpy 函数需要逐字节复制内存区域。这个函数将从源内存地址复制指定数量的字节到目标内存地址,不进行任何类型的检查或优化。

以下是模拟实现 memcpy 函数的示例代码:

#include <stdio.h>

// 模拟实现 memcpy 函数
void *my_memcpy(void *dest, const void *src, size_t n) 
{
    // 类型转换为 char* 类型,以便进行字节级的复制
    char *d = (char *)dest;
    const char *s = (const char *)src;

    // 循环复制每个字节
    for (size_t i = 0; i < n; i++) 
    {
        d[i] = s[i];
    }

    // 返回目标内存地址
    return dest;
}

int main() 
{
    int src[] = {1, 2, 3, 4, 5};
    int dest[5] = {0};
    my_memcpy(dest, src, sizeof(src));

    for (int i = 0; i < sizeof(src) / sizeof(src[0]); i++) 
    {
        printf("%d ", dest[i]);
    }
    printf("\n");

    return 0;
}

代码说明:

  1. 函数定义my_memcpy 函数接受三个参数:目标内存地址 dest、源内存地址 src 和要复制的字节数 n
  2. 类型转换:将 dest 和 src 转换为 char* 类型,以便进行字节级的复制。
  3. 复制字节:使用 for 循环逐字节复制内存区域。
  4. 返回值:函数返回目标内存地址 dest

这个模拟实现的 my_memcpy 函数在功能上与标准库中的 memcpy 函数相同,它正确地复制了指定数量的字节。这种方法的时间复杂度是 O(n),其中 n 是要复制的字节数。

请注意,这个简单的实现没有考虑对齐和优化,它只是提供了基本的字节复制功能。在实际的库实现中,memcpy 可能会使用特定的硬件指令和优化技术来提高性能。此外,如果源和目标内存区域重叠,memcpy 的行为是未定义的,通常需要使用 memmove 函数来处理重叠区域的复制。

12.模拟实现memove函数

  

memmove 函数用于复制内存区域,与 memcpy 函数类似,但 memmove 可以处理源内存和目标内存重叠的情况。在模拟实现 memmove 函数时,我们需要考虑到内存重叠的问题,并确保在复制过程中不会覆盖尚未复制的数据。

以下是模拟实现 memmove 函数的示例代码:

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

// 模拟实现 memmove 函数
void *my_memmove(void *dest, const void *src, size_t n) 
{
    char *d = (char *)dest;
    const char *s = (const char *)src;

    // 检查源内存和目标内存是否重叠
    if (s < d && s + n > d) 
    {
        // 向后复制,从目标内存的末尾开始
        d += n - 1;
        s += n - 1;
        while (n--) 
        {
            *d-- = *s--;
        }
    } 
      else 
    {
        // 向前复制,从目标内存的开始处开始
        while (n--) 
        {
            *d++ = *s++;
        }
    }

    // 返回目标内存地址
    return dest;
}

int main()
 {
    char src[] = "Hello, World!";
    char dest[20];
    my_memmove(dest, src, strlen(src) + 1); // 包括空终止符

    printf("Copied string: %s\n", dest);

    return 0;
}

代码说明:

  1. 函数定义my_memmove 函数接受三个参数:目标内存地址 dest、源内存地址 src 和要复制的字节数 n
  2. 类型转换:将 dest 和 src 转换为 char* 类型,以便进行字节级的复制。
  3. 检查重叠:通过比较源内存和目标内存的地址,确定是否需要向后复制以避免覆盖尚未复制的数据。
  4. 向后复制:如果内存重叠,从目标内存的末尾开始复制。
  5. 向前复制:如果不重叠,从目标内存的开始处开始复制。
  6. 返回值:函数返回目标内存地址 dest

这个模拟实现的 my_memmove 函数在功能上与标准库中的 memmove 函数相同,它正确地处理了内存重叠的情况,并复制了指定数量的字节。这种方法的时间复杂度是 O(n),其中 n 是要复制的字节数。

请注意,这个简单的实现没有考虑对齐和优化,它只是提供了基本的字节复制功能。在实际的库实现中,memmove 可能会使用特定的硬件指令和优化技术来提高性能。

13.模拟实现memcmp函数

  

模拟实现 memcmp 函数,我们需要编写一个函数来比较两个内存区域的前 n 个字节,并根据比较结果返回一个整数。

以下是模拟实现 memcmp 函数的示例代码:

#include <stdio.h>

// 模拟实现 memcmp 函数
int my_memcmp(const void *str1, const void *str2, size_t n) 
{
    const unsigned char *s1 = (const unsigned char *)str1;
    const unsigned char *s2 = (const unsigned char *)str2;

    // 比较每个字节,直到找到不相等的字节或达到 n
    while (n-- > 0 && *s1 == *s2) 
    {
        s1++;
        s2++;
    }

    // 如果找到不相等的字节,返回它们的差值
    if (n == 0) 
    {
        return 0; // 所有字节都相等
    } else 
    {
        return (int)(*s1 - *s2);
    }
}

int main() 
{
    const char str1[] = "Hello, World!";
    const char str2[] = "Hello, C++";
    const char str3[] = "Hello, World!";

    printf("str1 vs str2: %d\n", my_memcmp(str1, str2, sizeof(str1) - 1)); // 应该输出负数
    printf("str1 vs str3: %d\n", my_memcmp(str1, str3, sizeof(str1) - 1)); // 应该输出 0

    return 0;
}

代码说明:

  1. 函数定义my_memcmp 函数接受三个参数:两个指向内存区域的指针 str1 和 str2,以及要比较的字节数 n
  2. 类型转换:将 str1 和 str2 转换为 const unsigned char* 类型,以便进行字节级的比较。
  3. 比较字节:使用 while 循环比较每个字节,直到找到不相等的字节或达到 n
  4. 返回结果:如果所有字节都相等,返回 0;如果找到不相等的字节,返回它们的差值。

这个模拟实现的 my_memcmp 函数在功能上与标准库中的 memcmp 函数相同,它正确地比较了两个内存区域的前 n 个字节,并根据比较结果返回了一个整数。这种方法的时间复杂度是 O(n),其中 n 是要比较的字节数。

请注意,这个简单的实现没有考虑对齐和优化,它只是提供了基本的字节比较功能。在实际的库实现中,memcmp 可能会使用特定的硬件指令和优化技术来提高性能。

结语

好咯,以上就是所有的模拟实现分享啦,好事需多磨,好的技术也是一样,只有巩固好基础知识,才能在拔高的路上少一些停顿。最后,祝愿所有正在努力提升自身技术的小伙伴们能够早日达到自己的目标,冲呀!


原文地址:https://blog.csdn.net/Code_Allen/article/details/143524398

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!