ZetCode

C getdelim 函数

最后修改日期:2025 年 4 月 6 日

getdelim 函数是 C 语言中一个强大的工具,用于读取可变长度的输入行。与 fgets 不同,它自动处理内存分配,非常适合处理未知大小的输入。本教程将探讨 getdelim 的参数、返回值和实际应用。您将学会如何高效地读取文件、处理自定义分隔符以及正确管理内存。掌握 getdelim 将提升您 C 程序中的输入处理能力。

什么是 getdelim?

getdelim 函数读取输入,直到遇到指定的分隔符或文件结束符。它会根据需要动态分配内存,并将结果存储在提供的缓冲区中。该函数接受四个参数:指向缓冲区的指针、缓冲区大小、分隔符字符以及输入流。成功时,它返回读取的字符数(不包括空终止符)。失败时,它返回 -1,并设置 errno 来指示错误。

基本的 getdelim 用法

此示例演示了如何使用 getdelim 从标准输入读取一行。

basic_getdelim.c
#include <stdio.h>
#include <stdlib.h>

int main() {
    char *line = NULL;
    size_t len = 0;
    ssize_t read;

    printf("Enter a line of text: ");
    read = getdelim(&line, &len, '\n', stdin);

    if (read == -1) {
        perror("getdelim failed");
        free(line);
        return 1;
    }

    printf("You entered: %s", line);
    free(line);
    return 0;
}

在这里,getdelimstdin 读取,直到遇到换行符。line 指针最初为 NULL,允许 getdelim 按需分配内存。len 变量跟踪缓冲区大小。使用后,我们释放分配的内存以防止内存泄漏。这种方法可以处理任何长度的输入,而不会发生缓冲区溢出。

从文件读取

了解如何使用 getdelim 逐行读取整个文件。

file_reading.c
#include <stdio.h>
#include <stdlib.h>

int main() {
    FILE *fp;
    char *line = NULL;
    size_t len = 0;
    ssize_t read;

    fp = fopen("data.txt", "r");
    if (fp == NULL) {
        perror("Failed to open file");
        return 1;
    }

    while ((read = getdelim(&line, &len, '\n', fp)) != -1) {
        printf("Line length: %zu\n", read);
        printf("Content: %s", line);
    }

    free(line);
    fclose(fp);
    return 0;
}

此代码打开“data.txt”文件并逐行读取。如果一行超过当前缓冲区大小,getdelim 函数会自动重新分配内存。循环一直持续到 getdelim 返回 -1(EOF)。每次迭代都会打印行长度和内容。记得在使用完毕后释放缓冲区并关闭文件。

自定义分隔符

使用自定义分隔符和 getdelim 解析特殊格式。

custom_delimiter.c
#include <stdio.h>
#include <stdlib.h>

int main() {
    char *token = NULL;
    size_t len = 0;
    ssize_t read;

    printf("Enter items separated by commas: ");
    read = getdelim(&token, &len, ',', stdin);

    while (read != -1) {
        printf("Token: %s\n", token);
        read = getdelim(&token, &len, ',', stdin);
    }

    free(token);
    return 0;
}

在这里,getdelim 读取输入,直到找到逗号。循环分别处理每个标记。请注意,分隔符会保留在输出中,并且后续调用会从前一个调用中断的地方继续。此技术对于解析 CSV 数据或自定义文件格式非常有用。处理后务必释放分配的缓冲区。

处理二进制数据

使用 getdelim 处理包含空字符的二进制数据。

binary_data.c
#include <stdio.h>
#include <stdlib.h>

int main() {
    FILE *fp;
    char *data = NULL;
    size_t len = 0;
    ssize_t read;

    fp = fopen("binary.dat", "rb");
    if (fp == NULL) {
        perror("Failed to open file");
        return 1;
    }

    read = getdelim(&data, &len, '\0', fp);
    if (read != -1) {
        printf("Read %zd bytes of binary data\n", read);
    }

    free(data);
    fclose(fp);
    return 0;
}

此示例使用空字符('\0')作为分隔符来读取二进制数据。与基于字符串的函数不同,getdelim 可以正确处理嵌入的空字符。文件以二进制模式(“rb”)打开,以防止特定于平台的换行符转换。该函数读取,直到遇到空字节或文件结束符。

错误处理

使用 getdelim 进行正确的错误处理可确保程序的健壮性。

error_handling.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main() {
    char *line = NULL;
    size_t len = 0;
    ssize_t read;

    read = getdelim(&line, &len, '\n', stdin);
    if (read == -1) {
        if (errno == EINVAL) {
            fprintf(stderr, "Invalid parameters\n");
        } else if (errno == ENOMEM) {
            fprintf(stderr, "Memory allocation failed\n");
        } else {
            perror("getdelim error");
        }
        free(line);
        return 1;
    }

    printf("Success: %s", line);
    free(line);
    return 0;
}

此代码演示了对 getdelim 的全面错误处理。它检查特定的错误条件(无效参数或内存分配失败)并提供适当的反馈。errno 变量包含具体的错误代码。即使发生错误,也要始终释放资源。

读取固定大小的块

使用预先分配的缓冲区和 getdelim 进行固定大小的读取。

fixed_buffer.c
#include <stdio.h>
#include <stdlib.h>

#define BUF_SIZE 256

int main() {
    char buffer[BUF_SIZE];
    size_t len = BUF_SIZE;
    ssize_t read;

    printf("Enter input: ");
    read = getdelim(&buffer, &len, '\n', stdin);

    if (read == -1) {
        perror("getdelim failed");
        return 1;
    }

    printf("Read %zd bytes: %s", read, buffer);
    return 0;
}

此示例使用固定大小的缓冲区而不是动态分配。len 变量被初始化为缓冲区大小。如果输入超过缓冲区大小,getdelim 将返回 -1,并将 errno 设置为 ENOMEM。当您想限制内存使用但仍能从 getdelim 的功能中受益时,此方法很有用。

处理多个分隔符

通过多次调用 getdelim 实现多分隔符解析器。

multi_delimiter.c
#include <stdio.h>
#include <stdlib.h>

int main() {
    char *segment = NULL;
    size_t len = 0;
    ssize_t read;
    const char delimiters[] = {',', ';', ':', '\0'};

    printf("Enter text with mixed delimiters: ");
    
    for (int i = 0; i < sizeof(delimiters); i++) {
        read = getdelim(&segment, &len, delimiters[i], stdin);
        if (read == -1) break;
        printf("Segment %d (%c): %s\n", i+1, delimiters[i], segment);
    }

    free(segment);
    return 0;
}

这个高级示例处理带有多个分隔符的输入。循环遍历分隔符数组,依次使用 getdelim。每次调用都会读取直到遇到下一个分隔符。此技术对于解析具有多种分隔符类型的复杂输入格式非常有用。

使用 getdelim 的最佳实践

来源

getdelim man 页

本教程探讨了通用的 getdelim 函数,从基本行读取到高级解析技术。凭借动态内存管理和灵活的分隔符处理,getdelim 是 C 语言输入处理的强大工具。

作者

我叫 Jan Bodnar,是一名敬业的程序员,对编码充满热情。自 2007 年以来,我通过 1,400 多篇文章和 8 本电子书分享我的专业知识。凭借十多年的教学经验,我致力于让编程变得易于理解和引人入胜。

列表 C 标准库