C语言实用代码片段大全

本文整理了 C 语言开发中常用的代码片段,涵盖字符串处理、文件操作、内存管理、时间处理等场景。这些代码经过实际验证,可直接拷贝使用。

字符串处理

安全字符串复制

避免缓冲区溢出的安全复制函数:

safe_strcpy.c - 安全字符串复制
#include 
#include 
#include 

/* 安全字符串复制,自动处理长度和终止符 */
char *safe_strcpy(char *dest, const char *src, size_t dest_size) {
    if (dest == NULL || src == NULL || dest_size == 0) {
        return NULL;
    }
    size_t len = strlen(src);
    if (len >= dest_size) {
        len = dest_size - 1;  /* 截断,保留空间给 '\0' */
    }
    memcpy(dest, src, len);
    dest[len] = '\0';
    return dest;
}

/* 简化版宏 */
#define STRCPY(dst, src) safe_strcpy((dst), (src), sizeof(dst))

int main(void) {
    char buf[16];
    safe_strcpy(buf, "Hello, World!", sizeof(buf));
    printf("%s\n", buf);  /* 输出: Hello, World! */

    safe_strcpy(buf, "This is a very long string that will be truncated", sizeof(buf));
    printf("%s\n", buf);  /* 输出: This is a very */
    return 0;
}

字符串分割

类似 Python split 的字符串分割实现:

str_split.c - 字符串分割
#include 
#include 
#include 

typedef struct {
    char **items;
    size_t count;
} SplitResult;

void split_result_free(SplitResult *r) {
    if (r->items) {
        for (size_t i = 0; i < r->count; i++) {
            free(r->items[i]);
        }
        free(r->items);
    }
    r->items = NULL;
    r->count = 0;
}

SplitResult str_split(const char *str, char delim) {
    SplitResult result = {NULL, 0};
    if (str == NULL) return result;

    size_t len = strlen(str);
    size_t capacity = 4;
    result.items = malloc(capacity * sizeof(char *));
    if (!result.items) return result;

    const char *start = str;
    const char *p = str;

    while (*p) {
        if (*p == delim) {
            size_t tok_len = p - start;
            char *token = malloc(tok_len + 1);
            if (token) {
                memcpy(token, start, tok_len);
                token[tok_len] = '\0';
                if (result.count >= capacity) {
                    capacity *= 2;
                    result.items = realloc(result.items, capacity * sizeof(char *));
                }
                result.items[result.count++] = token;
            }
            start = p + 1;
        }
        p++;
    }

    /* 处理最后一个字段 */
    size_t tok_len = p - start;
    if (tok_len > 0 || (tok_len == 0 && len == 0)) {
        char *token = malloc(tok_len + 1);
        if (token) {
            memcpy(token, start, tok_len);
            token[tok_len] = '\0';
            result.items[result.count++] = token;
        }
    }

    return result;
}

int main(void) {
    SplitResult r = str_split("apple,banana,orange,grape", ',');
    for (size_t i = 0; i < r.count; i++) {
        printf("[%zu] %s\n", i, r.items[i]);
    }
    split_result_free(&r);
    return 0;
}

文件操作

读取整个文件到内存

一次性读取文件全部内容:

read_file.c - 读取整个文件
#include 
#include 

/* 读取文件到内存,返回内容并通过 out_size 返回大小 */
char *read_file(const char *path, size_t *out_size) {
    FILE *fp = fopen(path, "rb");
    if (!fp) return NULL;

    fseek(fp, 0, SEEK_END);
    long size = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    if (size < 0) {
        fclose(fp);
        return NULL;
    }

    char *content = malloc(size + 1);
    if (!content) {
        fclose(fp);
        return NULL;
    }

    size_t read = fread(content, 1, size, fp);
    content[read] = '\0';
    fclose(fp);

    if (out_size) *out_size = read;
    return content;
}

/* 写入文件 */
int write_file(const char *path, const char *content, size_t size) {
    FILE *fp = fopen(path, "wb");
    if (!fp) return -1;

    size_t written = fwrite(content, 1, size, fp);
    fclose(fp);

    return (written == size) ? 0 : -1;
}

int main(void) {
    size_t size;
    char *content = read_file("test.txt", &size);
    if (content) {
        printf("Read %zu bytes: %s\n", size, content);
        free(content);
    }
    return 0;
}

内存管理

内存池分配器

预先分配内存池,避免频繁 malloc:

mem_pool.c - 简单内存池
#include 
#include 
#include 

typedef struct MemPool {
    char *buffer;
    size_t capacity;
    size_t offset;
} MemPool;

void pool_init(MemPool *pool, size_t capacity) {
    pool->buffer = malloc(capacity);
    pool->capacity = capacity;
    pool->offset = 0;
}

void *pool_alloc(MemPool *pool, size_t size) {
    /* 8 字节对齐 */
    size_t aligned = (size + 7) & ~7;
    if (pool->offset + aligned > pool->capacity) {
        return NULL;
    }
    void *ptr = pool->buffer + pool->offset;
    pool->offset += aligned;
    return ptr;
}

void pool_reset(MemPool *pool) {
    pool->offset = 0;
}

void pool_destroy(MemPool *pool) {
    free(pool->buffer);
    pool->buffer = NULL;
}

/* 便捷宏,每次分配时自动计算类型大小 */
#define POOL_ALLOC(pool, type) ((type *)pool_alloc((pool), sizeof(type)))

int main(void) {
    MemPool pool;
    pool_init(&pool, 4096);

    int *a = POOL_ALLOC(&pool, int);
    double *b = POOL_ALLOC(&pool, double);
    char *c = pool_alloc(&pool, 128);

    *a = 42;
    *b = 3.14;
    strcpy(c, "Hello from pool!");

    printf("a=%d, b=%f, c=%s\n", *a, *b, c);
    printf("Used: %zu / %zu bytes\n", pool.offset, pool.capacity);

    pool_destroy(&pool);
    return 0;
}

时间处理

高精度计时器

使用 clock_gettime 实现微秒级精度计时:

high_res_timer.c - 高精度计时器
#include 
#include 
#include 

typedef struct {
    struct timespec start;
    struct timespec end;
} Timer;

void timer_start(Timer *t) {
    clock_gettime(CLOCK_MONOTONIC, &t->start);
}

void timer_stop(Timer *t) {
    clock_gettime(CLOCK_MONOTONIC, &t->end);
}

double timer_elapsed_ms(Timer *t) {
    double s = (t->end.tv_sec - t->start.tv_sec) * 1000.0;
    double ns = (t->end.tv_nsec - t->start.tv_nsec) / 1000000.0;
    return s + ns;
}

double timer_elapsed_us(Timer *t) {
    double s = (t->end.tv_sec - t->start.tv_sec) * 1000000.0;
    double ns = (t->end.tv_nsec - t->start.tv_nsec) / 1000.0;
    return s + ns;
}

/* 简单性能测试宏 */
#define BENCHMARK(name, code) do { \
    Timer _t; \
    timer_start(&_t); \
    code; \
    timer_stop(&_t); \
    printf(name " took %.2f ms\n", timer_elapsed_ms(&_t)); \
} while(0)

int main(void) {
    Timer t;
    timer_start(&t);

    /* 模拟一些工作 */
    volatile long sum = 0;
    for (int i = 0; i < 100000000; i++) {
        sum += i;
    }

    timer_stop(&t);
    printf("elapsed: %.2f ms (%.2f us)\n",
           timer_elapsed_ms(&t), timer_elapsed_us(&t));
    return 0;
}

错误处理工具

断言与错误检查宏

实用的调试和错误处理宏:

error_macros.c - 错误处理宏
#include 
#include 
#include 

/* 条件断言,为真则输出警告 */
#define ASSERT(cond, msg) do { \
    if (!(cond)) fprintf(stderr, "Assertion failed: %s\n", msg); \
} while(0)

/* 条件致命错误,为假则打印并退出 */
#define REQUIRE(cond, msg) do { \
    if (!(cond)) { \
        fprintf(stderr, "Error: %s\n", msg); \
        exit(EXIT_FAILURE); \
    } \
} while(0)

/* 检查函数返回值,为负则打印错误并goto到错误标签 */
#define CHECK(call) do { \
    int _err = (call); \
    if (_err < 0) { \
        perror(#call); \
        goto err; \
    } \
} while(0)

/* 检查空指针 */
#define NULL_CHECK(ptr) REQUIRE((ptr) != NULL, #ptr " is NULL")

/* 简化错误处理函数 */
void die(const char *msg) {
    fprintf(stderr, "Fatal: %s\n", msg);
    exit(EXIT_FAILURE);
}

void die_errno(const char *msg) {
    perror(msg);
    exit(EXIT_FAILURE);
}

int main(void) {
    /* 示例用法 */
    FILE *fp = fopen("nonexistent.txt", "r");
    if (!fp) {
        die_errno("Failed to open file");
    }
    fclose(fp);
    return 0;
}

容器实现

动态数组

类似 std::vector 的动态数组实现:

dynamic_array.c - 动态数组容器
#include 
#include 
#include 

#define DA_INIT_CAP 4

typedef struct {
    int *data;
    size_t size;
    size_t capacity;
} DynamicArray;

void da_init(DynamicArray *da) {
    da->data = malloc(DA_INIT_CAP * sizeof(int));
    da->size = 0;
    da->capacity = DA_INIT_CAP;
}

void da_push(DynamicArray *da, int val) {
    if (da->size >= da->capacity) {
        da->capacity *= 2;
        da->data = realloc(da->data, da->capacity * sizeof(int));
    }
    da->data[da->size++] = val;
}

void da_free(DynamicArray *da) {
    free(da->data);
    da->data = NULL;
    da->size = da->capacity = 0;
}

/* 泛型版本 - 用宏实现 */
#define DA_TYPE(type, name) typedef struct { \
    type *data; \
    size_t size; \
    size_t capacity; \
} name; \
void name##_init(name *da) { \
    da->data = malloc(4 * sizeof(type)); \
    da->size = 0; \
    da->capacity = 4; \
} \
void name##_push(name *da, type val) { \
    if (da->size >= da->capacity) { \
        da->capacity *= 2; \
        da->data = realloc(da->data, da->capacity * sizeof(type)); \
    } \
    da->data[da->size++] = val; \
} \
void name##_free(name *da) { \
    free(da->data); \
    da->data = NULL; \
    da->size = da->capacity = 0; \
}

DA_TYPE(char, CharArray)
DA_TYPE(double, DoubleArray)

int main(void) {
    DynamicArray arr;
    da_init(&arr);

    for (int i = 0; i < 100; i++) {
        da_push(&arr, i * 10);
    }

    printf("size=%zu, capacity=%zu\n", arr.size, arr.capacity);
    printf("arr[50]=%d\n", arr.data[50]);

    da_free(&arr);
    return 0;
}

总结

这些代码片段涵盖了 C 语言开发中的高频场景。建议将这些代码保存为独立的头文件或源文件,需要时直接 include 即可。祝编码愉快!