目录
前言
本文主要是对strncat,qsort,atoi的模拟实现
一、模拟实现strncat
C 库函数 char *strncat(char *dest, const char *src, size_t n) 把 src 所指向的字符串追加到 dest 所指向的字符串的结尾,直到 n 字符长度为止。
实现起来很容易,但要注意细节
# 关键点
- dest=NULL` 时不能复制**,因为无法写入 `NULL` 指针。
- src=NULL` 时也不能复制**,因为无法读取 `NULL` 指针。
- num=0` 时直接返回 `dest`**,因为不需要追加任何字符。
- 标准库 `strncat` 的行为**:它不检查 `dest` 或 `src` 是否为 `NULL`,直接解引用它们,所以调用者必须确保它们有效。但我们在模拟实现时,可以增加安全检查,避免崩溃。
参数
- dest -- 指向目标数组,该数组包含了一个 C 字符串,且足够容纳追加后的字符串,包括额外的空字符。
- src -- 要追加的字符串。
- n -- 要追加的最大字符数。
代码演示:
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include<windows.h>
char* my_strncat(char* dest, const char* src, size_t num) {
if ( dest==NULL||src == NULL||num==0) {
return dest;
}
char* a = dest;
while (*dest)dest++;
while ((*dest++ = *src++) && num--);
*dest = '\0';
return a;
}
int main() {
char a[] = "jfskjfsj";
char b[] = "shffhs";
my_strncat(a, b, 3);
puts(a);
my_strncat(a ,b, 7);
puts(a);
char str1[20];
char str2[20];
strcpy(str1, "To be ");
strcpy(str2, "or not to be");
strncat(str1, str2, 6);
puts(str1);
system("pause");
return 0;
}
#include <stdio.h>
#include <assert.h>
char* my_strncat(char* dest, const char* src, size_t num) {
if (dest == NULL) { // 如果 dest 是 NULL,直接返回 NULL
return NULL;
}
if (src == NULL || num == 0) { // 如果 src 是 NULL 或 num=0,直接返回 dest
return dest;
}
char* a = dest;
// 找到 dest 的末尾
while (*dest) {
dest++;
}
// 复制最多 num 个字符
while (num-- && (*dest++ = *src++)) {
// 空循环体
}
// 确保字符串以 '\0' 结尾
*dest = '\0';
return a;
}
int main() {
char a[20] = "hello";
char b[] = "world";
my_strncat(a, b, 3); // a 变成 "hellowor"
puts(a);
// 测试 dest=NULL 的情况
char* null_dest = NULL;
my_strncat(null_dest, b, 3); // 不会崩溃,直接返回 NULL
puts(null_dest);
// 测试 src=NULL 的情况
my_strncat(a, NULL, 3); // 不会崩溃,直接返回 a
puts(a);
return 0;
}
二、模拟实现qsort
qsort
是 C 标准库中提供的一个函数,用于对数组进行快速排序。它在 <stdlib.h>
头文件中定义。qsort
使用的是快速排序算法(quicksort),这是一种高效的排序算法,平均时间复杂度为 O(n log n)。
C 库函数 void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*)) 对数组进行排序。
参数
base
: 指向待排序数组的第一个元素的指针。nitems
: 数组中的元素数量。size
: 数组中每个元素的大小(以字节为单位)。compar
: 比较函数的指针,该函数用于比较两个元素。比较函数应当返回一个整数,表示比较结果:- 小于零:表示第一个元素小于第二个元素。
- 等于零:表示两个元素相等。
- 大于零:表示第一个元素大于第二个元素。
代码演示:
#include <stdio.h>
#include <string.h>
// 交换两个元素(逐字节交换)
void swap(void* a, void* b, size_t size) {
char* pa = (char*)a;
char* pb = (char*)b;
for (size_t i = 0; i < size; i++) {
char tmp = pa[i];
pa[i] = pb[i];
pb[i] = tmp;
}
}
// Hoare 分区法
int partition(void* base, int low, int high, size_t size, int (*compar)(const void*, const void*)) {
char* arr = (char*)base;
void* pivot = arr + high * size; // 选择最后一个元素作为 pivot
int i = low - 1;
for (int j = low; j <= high - 1; j++) {
if (compar(arr + j * size, pivot) <= 0) {
i++;
swap(arr + i * size, arr + j * size, size);
}
}
swap(arr + (i + 1) * size, arr + high * size, size);
return i + 1;
}
// 递归快速排序
void quick_sort(void* base, int low, int high, size_t size, int (*compar)(const void*, const void*)) {
if (low < high) {
int pi = partition(base, low, high, size, compar);
quick_sort(base, low, pi - 1, size, compar);
quick_sort(base, pi + 1, high, size, compar);
}
}
// 模拟 qsort
void my_qsort(void* base, size_t num, size_t size, int (*compar)(const void*, const void*)) {
if (base == NULL || num == 0 || size == 0 || compar == NULL) {
return; // 无效参数直接返回
}
quick_sort(base, 0, num - 1, size, compar);
}
// 比较函数(整型)
int cmp(const void* a, const void* b) {
return *(int*)a - *(int*)b;
}
int main() {
int arr[] = {88,999,0, 5, 2, 8, 1, 3 };
size_t n = sizeof(arr) / sizeof(arr[0]);
my_qsort(arr, n, sizeof(int), cmp);
for (size_t i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
三、模拟实现atoi
C 库函数 int atoi(const char *str) 把参数 str 所指向的字符串转换为一个整数(类型为 int 型)。
声明
下面是 atoi() 函数的声明。
int atoi(const char *str)
参数
- str -- 要转换为整数的字符串。
代码演示:
#include<stdio.h>
#include <ctype.h>
#include <limits.h>
#include<string.h>
int my_atoi(const char* str) {
int flag = 1;
long result = 0; // 使用long来检测溢出
// 跳过前导空白字符
while (isspace(*str))str++;
// 处理可选符号
if (*str == '+') {
str++;
}
else if (*str == '-') {
flag = -1;
str++;
}
// 转换数字部分
while (isdigit(*str)) {
result = result * 10 + (*str - '0');
str++;
// 检查溢出
if (flag == 1 && result > INT_MAX) {
return INT_MAX;
}
else if (flag == -1 && -result < INT_MIN) {
return INT_MIN;
}
}
return (int)(flag * result);
}
int main() {
char a[] = "123458899";
int ret = my_atoi(a);
printf("%d\n ", ret);
int val;
char str[20] = "98993489";
val = my_atoi(str);
printf("字符串值 = %s, 整型值 = %d\n", str, val);
char str2[20] = "runoob.com";
val = my_atoi(str2);
printf("字符串值 = %s, 整型值 = %d\n", str2, val);
return 0;
}
总结
关于本篇的内容就结束了,对你有帮助的可以点个赞