# 一些函数:

# <stdarg.h >

# 1. 可变参数

int func_name(int num, ...); // 声明方式,num 代表输入的个数,当然也可以加一些其他的要传的变量在前面

在函数定义中创建一个 va_list 类型变量,该类型是在 stdarg.h 头文件中定义的。

va_list valist;

使用 int 类型的参数(一般就是上面的 arg1)和 va_start() 宏来初始化 va_list 变量为一个参数列表。宏 va_start() 是在 stdarg.h 头文件中定义的。

// 为 num 个参数初始化 valist
va_start(valist, num);

使用 va_arg() 宏和 va_list 变量来访问参数列表中的每个项。

for (i = 0; i < num; i++){
       sum += va_arg(valist, int); // 假设后续输入的都是 int 类型
    }

使用宏 va_end() 来清理赋予 va_list 变量的内存。

var_end(valist);

输出平均值:

#include <stdio.h>
#include <stdarg.h>

double average(int num,...)
{

va_list valist;
double sum = 0.0;
int i;
/* 为 num 个参数初始化 valist */
va_start(valist, num);
/* 访问所有赋给 valist 的参数 */
for (i = 0; i < num; i++)
{
   sum += va_arg(valist, int);
}
/* 清理为 valist 保留的内存 */
va_end(valist);
return sum/num;

}

int main()
{
printf("Average of 2, 3, 4, 5 = %f\n", average(4, 2,3,4,5));
printf("Average of 5, 10, 15 = %f\n", average(3, 5,10,15));
}

# <string.h>

# 1.memcpy()/memmove()

  • memcpy () 函数:用于从源内存区域复制数据到目标内存区域。它接受三个参数,即目标内存区域的指针、源内存区域的指针和要复制的数据大小(以字节为单位)。

    void *memcpy(void *dest, const void *src, size_t n);
    //n 是字节数,dest 是要复制到的地方的首地址,src 则是要复制的数据的首地址

    复制字符数组数据:

    #include <stdio.h> 
    #include <string.h> 
    int main() {    
    char source[] = "Hello, World!";   
    char target[20];     
    memcpy(target, source, strlen(source) + 1);// 复制 '\0'
    // 其他类型用 sizeof 即可
    printf("%s\n", target);     
    return 0; }
  • memmove () 函数:类似于 memcpy () 函数,但它可以处理重叠的内存区域(对于 memcpy (), 此时行为是未定义的)。它接受三个参数,即目标内存区域的指针、源内存区域的指针和要复制的数据大小(以字节为单位)。

    用法同上。如果重叠,就将 src 的对应个数的数据直接复制过去(覆盖导致的变化不会影响后续的复制)

比如

#include <stdio.h>
#include <string.h>
int main() {
    char arr[11] = "abcdefghij";
    memmove(arr + 1, arr + 2, 5);
    printf("%s\n", arr);
    return 0;
}
// 输出是 acdefgghij

2.memset

# 一些额外的东西:

# 1. 柔性数组(C99 以上)

可以使用它来实现动态可变长的结构体。

定义:

typedef struct FlexibleStruct {
    int count;
    int data[];// 相当于 int data [0];
} FlexibleStruct0;

注意:

一个结构体中只能有一个可变长的成员,并且该成员必须是最后一个成员。

FlexibleStruct *createFlexibleStruct(int numElements) {
    // 计算总共需要分配的内存大小,包括结构体本身和柔性数组部分
    // 柔性数组本身不算在 sizeof 中(这个 data [] 它不占内存)
    size_t totalSize = sizeof(FlexibleStruct) + numElements * sizeof(int);
    // 分配内存
    FlexibleStruct *fs = (FlexibleStruct *)malloc(totalSize);
    fs->count = numElements;
    return fs;
}

要一次性分配内存

排序算法:

1. 插入排序

#include <stdio.h>
 
// 函数声明
void insertion_sort(int arr[], int len);
 
int main() {
    int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };
    int len = sizeof(arr) / sizeof(arr[0]);  // 计算数组长度
 
    insertion_sort(arr, len);  // 调用插入排序函数
 
    // 打印排序后的数组
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
 
    return 0;
}
 
// 插入排序函数
void insertion_sort(int arr[], int len) {
    for (int i = 1; i < len; i++) {
        int temp = arr[i];  // 当前待插入的元素
        int j = i;
        // 向右移动大于 temp 的元素
        while (j > 0 && arr[j - 1] > temp) {
            arr[j] = arr[j - 1];
            j--;
        }
        arr[j] = temp;  // 插入元素到正确位置
    }
}

2. 希尔排序

它不是选择而是插入的改进

#include <stdio.h>
 
// 函数声明
void shell_sort(int arr[], int len);
 
int main() {
    int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };
    int len = sizeof(arr) / sizeof(arr[0]);  // 计算数组长度
 
    shell_sort(arr, len);  // 调用希尔排序函数
 
    // 打印排序后的数组
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
 
    return 0;
}
 
// 希尔排序函数
void shell_sort(int arr[], int len) {
    // 计算初始间隔
    for (int gap = len / 2; gap > 0; gap /= 2) {
        // 对每个间隔进行插入排序
        for (int i = gap; i < len; i++) {
            int temp = arr[i];  // 当前待插入的元素
            int j = i;
            // 移动大于 temp 的元素
            while (j >= gap && arr[j - gap] > temp) {
                arr[j] = arr[j - gap];
                j -= gap;
            }
            arr[j] = temp;  // 插入元素到正确位置
        }
    }
}

3. 归并排序

迭代法

#include <stdio.h>
#include <stdlib.h>
// 函数声明
int min(int x, int y);
void merge_sort(int arr[], int len);
int main() {
    int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };
    int len = sizeof(arr) / sizeof(arr[0]);  // 计算数组长度
    merge_sort(arr, len);  // 调用归并排序函数
    // 打印排序后的数组
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    return 0;
}
// 返回两个数中的最小值
int min(int x, int y) {
    return x < y ? x : y;
}
 
// 归并排序函数
void merge_sort(int arr[], int len) {
    int* a = arr;
    int* b = (int*) malloc(len * sizeof(int));
 
    if (b == NULL) {  // 检查内存分配是否成功
        fprintf(stderr, "Memory allocation failed\n");
        exit(EXIT_FAILURE);
    }
    for (int seg = 1; seg < len; seg += seg) {
        for (int start = 0; start < len; start += seg + seg) {
            int low = start;
            int mid = min(start + seg, len);
            int high = min(start + seg + seg, len);
            int k = low;
            int start1 = low, end1 = mid;
            int start2 = mid, end2 = high;
            // 合并两个子数组
            while (start1 < end1 && start2 < end2) {
                b[k++] = a[start1] < a[start2] ? a[start1++] : a[start2++];
            }
            while (start1 < end1) {
                b[k++] = a[start1++];
            }
            while (start2 < end2) {
                b[k++] = a[start2++];
            }
        }
        // 交换数组指针
        int* temp = a;
        a = b;
        b = temp;
    }
 
    // 如果 a 和 arr 不相同,则将 a 的内容复制回 arr
    if (a != arr) {
        for (int i = 0; i < len; i++) {
            b[i] = a[i];
        }
        b = a;
    }
    free(b);  // 释放内存
}

递归法

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
// 函数声明
void merge_sort_recursive(int arr[], int reg[], int start, int end);
void merge_sort(int arr[], const int len);
 
int main() {
    int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };
    int len = sizeof(arr) / sizeof(arr[0]);  // 计算数组长度
 
    merge_sort(arr, len);  // 调用归并排序函数
 
    // 打印排序后的数组
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
 
    return 0;
}
 
// 递归实现归并排序
void merge_sort_recursive(int arr[], int reg[], int start, int end) {
    if (start >= end)
        return;
 
    int mid = start + (end - start) / 2;
    int start1 = start, end1 = mid;
    int start2 = mid + 1, end2 = end;
 
    merge_sort_recursive(arr, reg, start1, end1);
    merge_sort_recursive(arr, reg, start2, end2);
 
    int k = start;
    while (start1 <= end1 && start2 <= end2) {
        reg[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];
    }
    while (start1 <= end1) {
        reg[k++] = arr[start1++];
    }
    while (start2 <= end2) {
        reg[k++] = arr[start2++];
    }
 
    // 使用 memcpy 进行数组复制,提高效率
    memcpy(arr + start, reg + start, (end - start + 1) * sizeof(int));
}
 
// 归并排序入口函数
void merge_sort(int arr[], const int len) {
    int* reg = (int*)malloc(len * sizeof(int));
    if (reg == NULL) {  // 检查内存分配是否成功
        fprintf(stderr, "Memory allocation failed\n");
        exit(EXIT_FAILURE);
    }
    merge_sort_recursive(arr, reg, 0, len - 1);
    free(reg);  // 释放内存
}

4. 快速排序

迭代法

#include <stdio.h>
// 范围结构体
typedef struct _Range {
    int start, end;
} Range;
// 创建新的范围
Range new_Range(int s, int e) {
    Range r;
    r.start = s;
    r.end = e;
    return r;
}
// 交换两个整数
void swap(int *x, int *y) {
    int t = *x;
    *x = *y;
    *y = t;
}
 
// 快速排序函数
void quick_sort(int arr[], const int len) {
    if (len <= 0)
        return; // 避免 len 等于负值时引发段错误(Segment Fault)
    Range r[len];
    int p = 0;
    r[p++] = new_Range(0, len - 1);
 
    while (p > 0) {
        Range range = r[--p];
        if (range.start >= range.end)
            continue;
 
        int mid = arr[(range.start + range.end) / 2]; // 选取中间点为基准点
        int left = range.start, right = range.end;
        do {
            while (arr[left] < mid) ++left;   // 检测基准点左侧是否符合要求
            while (arr[right] > mid) --right; // 检测基准点右侧是否符合要求
            if (left <= right) {
                swap(&arr[left], &arr[right]);
                left++;
                right--; // 移动指针以继续
            }
        } while (left <= right);
        if (range.start < right) r[p++] = new_Range(range.start, right);
        if (range.end > left) r[p++] = new_Range(left, range.end);
    }
}
int main() {
    int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
    int len = sizeof(arr) / sizeof(arr[0]); // 计算数组长度
    quick_sort(arr, len); // 调用快速排序函数
    // 打印排序后的数组
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    return 0;
}

递归法

#include <stdio.h>
// 交换两个整数
void swap(int *x, int *y) {
    int t = *x;
    *x = *y;
    *y = t;
}
// 递归实现快速排序
void quick_sort_recursive(int arr[], int start, int end) {
    if (start >= end)
        return;
    int mid = arr[end];
    int left = start, right = end - 1;
 
    while (left < right) {
        while (left < right && arr[left] < mid)
            left++;
        while (left < right && arr[right] >= mid)
            right--;
        swap(&arr[left], &arr[right]);
    }
    if (arr[left] >= arr[end])
        swap(&arr[left], &arr[end]);
    else
        left++;
    quick_sort_recursive(arr, start, left - 1);
    quick_sort_recursive(arr, left + 1, end);
}
// 快速排序入口函数
void quick_sort(int arr[], int len) {
    quick_sort_recursive(arr, 0, len - 1);
}
int main() {
    int arr[] = {22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70};
    int len = sizeof(arr) / sizeof(arr[0]); // 计算数组长度
    quick_sort(arr, len); // 调用快速排序函数
    // 打印排序后的数组
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    return 0;
}