模拟实现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++;}// 返回两个字符的差值,如果相等则为 0return (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,返回 0return (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; // 保存目标字符串的起始地址// 复制每个字符,直到遇到源字符串的结束或达到 nwhile (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++;}// 复制每个字符,直到遇到源字符串的结束或达到 nwhile (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++;}// 如果到达字符串末尾,返回 NULLif (*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{// 如果到达字符串末尾,设置静态变量为 NULLg_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;// 比较每个字节,直到找到不相等的字节或达到 nwhile (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)); // 应该输出 0return 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 可能会使用特定的硬件指令和优化技术来提高性能。

结语

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/4331.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

unity发布webGL

1.安装WebGL板块 打开unity&#xff0c;进入该界面&#xff0c;然后选择圈中图标 选择添加模块 选择下载WebGL Build Support 2.配置项目设置 打开一个unity项目&#xff0c;如图进行选择 如图进行操作 根据自己的情况进行配置&#xff08;也可直接点击构建和运行&#xff09…

基于势能的平面运动模拟

运动模拟 接前面递归调用——单向汉诺塔七边形最小分割弦 F m a Fma Fma F m a m d 2 r d t 2 F ma m \frac{{{d^2}\ r}}{{d{t^2}}} Fmamdt2d2 r​ F k Q q r 2 r ^ F k \frac{{Qq}}{{{r^2}}} \hat{r} Fkr2Qq​r^代码电荷的位置和值运动电荷的初始位置和速度计算距离计算…

SpringBoot在线教育系统:数据分析与报告

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

Linux开发工具——make/Makefile

目录 一、什么是makefile&#xff1f; 二、为什么要有makefile&#xff1f; 三、makefile的使用 1.依赖关系与依赖方法 2.伪目标 3.定义变量 4.特殊符号 四、makefile的执行逻辑 一、什么是makefile&#xff1f; Makefile是一种自动化构建工具&#xff0c;make是一条指…

BC146 添加逗号

BC146 添加逗号 import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main {public static void main(String[] args) {Scanner in new Scanner(System.in);String str in.next();StringBuilder s new StringBuilder(str);for(int …

【计算机视觉】深入浅出SLAM技术原理

引言 SLAM&#xff08;Simultaneous Localization and Mapping&#xff0c;同步定位与建图&#xff09;是机器人学和计算机视觉中的一个重要技术&#xff0c;它允许机器人在未知环境中自主导航&#xff0c;同时构建环境的地图并确定自身的精确位置。本文将详细介绍SLAM技术的基…

求平面连接线段组成的所有最小闭合区间

这个功能确实非常实用&#xff0c;我在过去开发地面分区编辑器时就曾应用过这一算法。最近&#xff0c;在新产品的开发中再次遇到了类似的需求。尽管之前已经实现过&#xff0c;但由于长时间未接触&#xff0c;对算法的具体细节有所遗忘&#xff0c;导致重新编写时耗费了不少时…

如何才能实时监测Mac的运行状态

实时监测Mac的运行状态&#xff0c;能够让我们更好的了解Mac的情况&#xff0c;因此如何才能监测Mac的运行状态很重要 State&#xff0c;实时监测你的Mac运行状态&#xff0c;能够直观的展示当前Mac的CPU、内存、硬盘、温度、风扇、网络信息以及开机时间等重要信息 除此之外&a…

强化学习介绍

目录标题 一、什么是强化学习二、强化学习的环境三、强化学习的目标四、强化学习中的数据从哪里来五、强化学习的独特性 一、什么是强化学习 强化学习是机器通过与环境交互来实现目标的一种计算方法。 机器和环境的一轮交互是指&#xff0c;机器在环境的一个状态下做一个动作决…

【算法】【优选算法】滑动窗口(上)

目录 一、滑动窗口简介二、209.⻓度最⼩的⼦数组2.1 滑动窗口2.2 暴力枚举 三、3.⽆重复字符的最⻓⼦串3.1 滑动窗口3.2 暴力枚举 四、1004.最⼤连续1的个数III4.1 滑动窗口4.2 暴力枚举 五、1658.将x减到0的最⼩操作数5.1 滑动窗口5.2 暴力枚举 一、滑动窗口简介 其实就是利用…

软考高级之系统架构师系列之构件开发模型

如标题所述&#xff0c;本文面向于软考高级&#xff0c;具体来说是系统架构师。 有些概念&#xff0c;如生命周期&#xff0c;开发的几个阶段&#xff0c;不同的教程有些许出入。 本文偏理论&#xff0c;要在理解的基础上加以记忆&#xff0c;用于应付软考&#xff0c;有些地…

机器人零位、工作空间、坐标系及其变换,以UR5e机器人为例

机器人中的主要坐标系 在机器人中&#xff0c;常用的坐标系包括&#xff1a; 基坐标系&#xff08;Base Frame&#xff09;&#xff1a;固定在机器人基座上的坐标系&#xff0c;用于描述机器人的整体位置和方向&#xff0c;是其他所有坐标系的参考点。 连杆坐标系&#xff08…

VMWARE ESXI VMFS阵列故障 服务器数据恢复

1&#xff1a;河南用户一台DELL R740 3块2.4T硬盘组的RAID5&#xff0c;早期坏了一个盘没有及时更换&#xff0c;这次又坏了一个&#xff0c;导致整组RAID5处于数据丢失的状态&#xff0c; 2&#xff1a;该服务器装的是VMware ESXI 6.7&#xff0c;用户把3块硬盘寄过来进行数据…

程序员开发速查表

作为一名苦逼的程序员&#xff0c;在开发的过程中&#xff0c;我们总是在各种编程语言中来回穿梭&#xff0c;忙完后端整前端&#xff0c;还得做一部分的运维工作&#xff0c;忙的我们有时候忘记语法&#xff0c;忘记编写规则&#xff0c;甚至混淆。这时候我们就希望有一个综合…

「Mac畅玩鸿蒙与硬件30」UI互动应用篇7 - 简易计步器

本篇将带你实现一个简易计步器应用&#xff0c;用户通过点击按钮增加步数并实时查看步数进度&#xff0c;目标步数为 10000 步。该项目示例展示了如何使用 Progress 组件和 Button 组件&#xff0c;并结合状态管理&#xff0c;实现交互式应用。 关键词 UI互动应用计步器Button…

直播系统搭建教程安装说明

需要安装的软件(宝塔【软件商店】中查找安装): 1.PHP7.0 ~ PHP7.3 需要安装的扩展:(宝塔【PHP管理】【安装扩展】中安装) *PDO PHP Extension * MBstring PHP Extension * CURL PHP Extension * Mylsqi PHP Extension * Redis PHP Extension * fileinfo PHP Extension …

@Async注解提升Spring Boot项目中API接口并发能力

文章目录 同步调用异步调用1: 启用异步支持2: 修改 Task 类异步回调基本概念使用 Future<String>使用 CompletableFuture<String>Future<String> 和 CompletableFuture<String>区别1. 基本概念2. 主要区别同步调用 同步调用是最直接的调用方式,调用方…

对齐自治 Aligned autonomy

对于有效的产品开发&#xff0c;我们想要的自主权不是 “随心所欲” &#xff0c;而是一种自主权&#xff0c;使团队能够自由行动&#xff0c;利用他们所有的能力朝着集体成果前进。这也称为“对齐自治”。 Aligned autonomy 2x2&#xff0c;来自 Spotify 的 Henrik Kniberg 工…

Spring Boot 与 Vue 共筑二手书籍交易卓越平台

作者介绍&#xff1a;✌️大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 &#x1f345;获取源码联系方式请查看文末&#x1f345; 推荐订阅精彩专栏 &#x1f447;&#x1f3fb; 避免错过下次更新 Springboot项目精选实战案例 更多项目…

物理验证Calibre LVS Debug案例之通过deleteEmptyModule解决LVS问题

上周帮助T12nm A55训练营学员debug一个Calibre LVS问题&#xff0c;小编觉得挺好的一个问题。这个问题之前没有遇到过&#xff0c;今天分享给大家。 数字IC后端先进工艺设计实现之TSMC 12nm 6Track工艺数字IC后端实现重点难点盘点 下图所示为Calibre LVS的报告。从报告中看到…