模拟实现C库函数~

用 XCO 库一键找出某个 ABAP 类的全部子类 ABAP XCO库子类枚举技术解析 本文介绍了在ABAP项目中如何利用XCO库高效获取类的继承层次结构。传统方法使用CL_ABAP_CLASSDESCR或手动维护映射表存在效率低、易遗漏的问题。新方法通过XCO库的IF_XCO_AO_CLASS接口,可简洁地获取父类的所有子类(包括间接子类)。 核心API链式调用: 获取类句柄:xco_cp_abap=>class() 导航子类集合:subclasses->all 获取结果:get()返回类引用表或get_names()返回类名列表 典型应用场景 阅读详情

上篇文章介绍完了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 函数时,必须确保 haystack 和 needle 都是有效的 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 可能会使用特定的硬件指令和优化技术来提高性能。

结语

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

【文献笔记】CVPR 2023|Attention-Based Point Cloud Edge Sampling 优点能够有效采出点云数据的边缘点分类任务性能优越不足没有设计出一个更好的上采样方法,导致分割任务的性能略低只考虑了边缘特征,没有利用其他几何特征。 阅读详情

相关推荐

Windows服务器XMRig挖矿病毒深度清除实战指南

XMRig是一种广泛用于Monero(XMR)加密货币挖矿的开源工具,其在Windows环境中的持久化机制已远超传统木马范畴,融合WMI事件订阅、服务伪装、PowerShell无文件执行与注册表隐写等多重反检测技术。理解其基于行为而非特征的生存逻辑,是实现有效检测与根除的前提。该技术具备强隐蔽性、高自愈性与网络通信合法化特征,常见于RDP弱口令爆破、SMB共享泄露及PowerShell远程执行等非漏洞类入侵场景。本文聚焦Windows原生命令与Sysinternals工具链,提供覆盖进程定位、WMI清理、服

weixin_30535843的博客 735

C语言程序设计——循环(3)

一般形式: do循环语句;如果expr为真,则返回do的位置继续循环。语句很简单,且break与continual的用法与其他循环一致,不作赘述。

XLZ_44847的博客 111

海康威视工业相机网络配置实战:从MVS软件操作到IP地址规划

本文详细介绍了海康威视工业相机的网络配置实战,从MVS软件操作到IP地址规划。重点讲解了IP设置的重要性、Windows系统下的网络配置步骤、避免IP冲突的技巧,以及MVS软件中的相机IP配置方法。帮助用户快速掌握工业相机的网络连接技术,确保稳定高效的图像采集。

weixin_30296405的博客 487

部分库函数的应用以及模拟实现

c语言部分库函数的讲解以及模拟实现

2301_79705195的博客 1209

<Verilog实现除法器> Verilog实现牛顿-拉夫逊(Newton-Raphson)除法器

阿斯顿阿斯顿啊啊是打发士大夫

IC跳跳鱼的博客 3586

用Python+NumPy手把手实现分数阶傅里叶变换(FRFT),搞定线性调频信号分析

本文详细介绍了如何使用Python和NumPy实现分数阶傅里叶变换(FRFT),特别针对线性调频信号(Chirp信号)分析。通过从零开始的代码实现和可视化案例,展示了FRFT在时变信号处理中的强大能力,帮助工程师和研究人员高效分析频率随时间变化的信号。

weixin_29062823的博客 218

【C语言】复习~常用库函数

C语言复习

iiiiisss的博客 1059

算法 | A*算法实现最优路径规划

启发式探索是利用问题拥有的启发信息来引导搜索,达到减少探索范围、降低问题复杂度的目的。A*寻路算法是启发式探索的一个典型实践,在寻路搜索的过程中,给每个节点绑定了一个估计值(即启发式),在对节点的遍历过程中采取估计值优先原则,估计值更优的节点会被优先遍历。...

不断学习,不断进步,提高自己 6635

C语言模拟实现部分库函数

介绍部分字符串库函数的模拟实现,包括strlen,strcpy,strcat,strcmp,strstr,strncpy,strncat,strncmp,memcpy,memmove等函数的模拟实现以及其它字符,字符串和内存库函数的用法介绍

0xFFFFFFFF 1385

Qt软件开发-Qt编译zlib完成文件压缩解压(win10)

在软件开发中进行有需求需要将生成的一些文件打包上传到服务器,或者从服务器下载压缩包下来内部解压。或者自己做一些打包工具,那么使用zlib开源就可以很方便的完成。接下来介绍在zlib在windows下如何利用Qt进行编译,调用,介绍mingw、msvc,32/64位编译办法,完成zip文件打包生成例子。可以单文件压缩打包,多文件压缩打包,目录压缩打包等等。

2218

【传感器模块项目实战】自动驾驶/机器人相关传感器原理及标定

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录系列文章目录前言一、IMU二、相机三、激光雷达四、轮速里程计五、GPS/RTK六、毫米波雷达总结 前言 认知有限,望大家多多包涵,有什么问题也希望能够与大家多交流,共同成长! 本文先对**【自动驾驶相关传感器原理及标定】**做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章 提示:以下是本篇文章正文内容 一、IMU IMU惯导系统的特性(imu_calc函数功能) IMU运行的

qq_35635374的博客 1232

C语言中部分库函数的模拟实现

部分C语言库函数的模拟实现

if212的博客 492

Anomalib库安装以及使用

Anomalib是一个专注于异常检测的深度学习库。它的目标是收集最新的异常检测算法,并提供用于在公共和私有数据集上进行基准测试的工具。该库提供了一系列已实现的异常检测算法,这些算法在最近的文献中有所描述。此外,Anomalib还提供了一套工具,方便开发人员开发和实现自定义模型。该库特别注重基于图像的异常检测,旨在识别数据集中的异常图像或图像中的异常像素区域。通过使用Anomalib,用户可以快速构建和评估各种异常检测算法,以满足其特定需求。

mingo_敏 5202

模拟实现C库函数(1)

当你行走了一段时间后,回头往往那不管是起初咿咿呀呀胡乱踩陷的小坑时,还是之后慢慢地、熟练地避开了水洼、泥淖,不同的时段,不同的境地,回首那时的稚嫩与热情,我想总该会留下些感慨和欣慰。我们通过访问str的每个字符,将下一个字符串的地址传递给递归函数并+1。很久没更新过C专栏的文章了,借复习(review)的机会,本节的内容针对我们常见、常用的C串库函数的模拟实现。我们都知道,strlen函数,求的是一个字符串的长度。那么当它遇到"\0"时,就结束。当指针-指针,得到的结果是,这个区域之间的个数。

RNGWGzZs的博客 542

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

模拟实现C库函数(2)

(unsigend char)s每次将原内存的比特位置位: 00000001。上一篇的模拟实现了好几个库函数,strlen\strcpy\memcpy\memmove,那么这一篇又会增加几个常用C库函数的模拟实现 memset\itoa\atoi。不过,对于设置0而言,memset(arr1, 0, sizeof(int) * 10)可以完美做到。比较32个位都是0。变量类型的本质只是标志从某一内存地址开始读取的位数,强制转换就是改变读取位数的大小。改变的不是变量本身,而是从内存中读取每个bit的方式。

RNGWGzZs的博客 558

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

C/C++(复习版) - C语言中重要的库函数模拟实现

可以看出,strstr如果str1中找到了字符串str2,返回的是找到的那个字符串的起始位置!对于内存重叠的拷贝要分情况处理,否则会覆盖掉原来的值,拷贝的内容不正确。

2401_83238095的博客 992

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

C语言——string.h下的基本库函数

为了⽅便操作字符和字符串,C语⾔标准库stype.h与string.h中提供了⼀系列库函数,接下来我们就学习⼀下这些函数使用以及模拟实现。

2401_89019969的博客 1483

《小猫猫大课堂》三轮3——字符函数和字符串函数及其模拟实现

字符串的使用 strlen​​​​​​​ const assert strcpy strcpy的模拟实现 strcat strcmp strcmp的应用及模拟实现 strncpy strncpy的应用 strncat strncmp strncmp的应用 strstr strtok strerror 字符分类函数 memcpy memmove memmove的应用及模拟实现 memcmp memcmp的模拟实现(VS下进行) memset memset的应用

ormstq的博客 1667

C语言:认识库函数strlen

认识库函数

2301_80689220的博客 692

【C语言】库函数实现及其模拟

C语言中部分的库函数实现及其模拟。

m0_74173089的博客 246

【C语言】模拟实现库函数 strcpy(复制字符串内容) 与 strlen(求字符串长度)

前言:对于库函数的使用,我们不仅要会使用方法,更要知晓使用原理,而知晓使用原理最好的方法就是模拟相应库函数的使用。 今天我们就来模拟 strcpy(复制字符串内容) 与 strlen(求字符串长度)这两个库函数的使用。 目录1.strlen的模拟:2.strcpy的模拟: 1.strlen的模拟: 首先我们要了解strlen这个库函数的使用方法,如图: 由图可知,strlen库函数的返回类型是无符号整型 (写成size_t 也等价于 unsigned int), 函数参数是 传进来的字符串数组地址 .

xqs196301的博客 829

C语言内存函数memcpy、memmove详细讲解及其模拟实现

也就是我们拷贝了多少个字节,内部的构造就比较简单,我们要明白的是void*是一个空指针不能直接进行解引用操作,所以我们强制类型转换将它改为char*类型再进行解引用操作,这样就可以让我们每个元素都是字节,那我们的地址呢地址也需要对他进行强制类型转换,这样我们每当指向一个地址后进行+1指向下一个地址这样我的arr2数组就会被修改。大小,int的字节大小是4,5*4也就是20个字节,然而我们的memcpy函数也是通过字节的个数,来访问我们的电脑因该拷贝多少个字节。对于重叠的内存我们需要memove来处理。

2301_79849400的博客 1238

库函数---C语言

strcpy详解源字符串必须以 ‘\0’结束(源字符串中间含有’\0’是时,只拷贝到’\0’之前的字符串)。会将源字符串中的 ‘\0’ 拷贝到目标空间。目标空间必须足够大,以确保能存放源字符串。目标空间必须可变(可被拷贝)。即不可为常量字符串.strncpy详解拷贝num个字符从源字符串到目标空间。如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个.int main()//不足补0return 0;

weixin_63685622的博客 1225

模拟strcmp库函数的实现(超详细)

这一篇,带你从零基础到完全掌握strcmp库函数的使用!

m0_70088010的博客 1251

C语言字符类库函数

大家平时在刷题的时候是否遇到一些比较麻烦的处理字符,字符串函数的题目。比如,将字符进行分类,大小写转化,计算字符串个数,拷贝字符串等。其实C语言提供了一系列库函数来帮组程序员实现对字符,字符串的快速处理。今天我们就来着重了解它们,并试着进行模拟实现。2.字符类我们介绍完了部分处理字符,字符串的库函数。在对其部分进行模拟实现的时候很容易发现,实现这些功能离不开指针。同时,也希望能在各位对指针的理解和使用上产生一点帮助。

2301_79444463的博客 1015

库函数atoi的功能及模拟实现

本文详细讲解了atoi库函数的使用及模拟实现。

qq_52907930的博客 323
上一篇: ~C.库函数的介绍~
下一篇: C~动态内存函数介绍
知困勉行的Allen
博客等级 码龄3年 279粉丝 33原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值