You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言解析文件到char**二维数组时末尾多余空行求助

C语言解析文件到二维字符数组时末尾多余空行的修复方案

我正在开发一个C语言函数,用于将文件解析为二维字符数组(char **),但目前遇到末尾出现多余空行的问题,学校要求必须使用getline()和fopen()函数,以下是我的代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

void my_free_word_array(char **word_array)
{
    size_t i = 0;
    if (!word_array) {
        return;
    }
    while (word_array[i] != NULL) {
        free(word_array[i]);
        ++i;
    }
    free(word_array);
}

ssize_t my_put_str_arr(char **arr, int fd)
{
    char cr = '\n';
    ssize_t count = 0;
    size_t i = 0;
    if (!arr)
        return -1;
    while (arr[i]) {
        count += write(fd, arr[i], strlen(arr[i]));
        count += write(fd, &cr, 1);
        i++;
    }
    return count;
}

void append_word_array(char ***array, char *line)
{
    size_t array_len = 0;
    while ((*array)[array_len] != NULL) {
        array_len++;
    }
    size_t len = strlen(line);
    if (line[len - 1] == '\n') {
        line[len - 1] = '\0';
    }
    (*array)[array_len] = strdup(line);
    (*array) = realloc((*array), (array_len + 2) * sizeof(char *));
    (*array)[array_len + 1] = NULL;
}

void fill_from_file(char ***array, FILE *file)
{
    char *line_buff = NULL;
    size_t line_buff_size = 0;
    ssize_t line_size = getline(&line_buff, &line_buff_size, file);
    while (line_size >= 0) {
        append_word_array(array, line_buff);
        free(line_buff);
        line_buff = NULL;
        line_size = getline(&line_buff, &line_buff_size, file);
    }
    free(line_buff);
}

char **my_load_file_to_word_array(const char *filepath)
{
    char **word_array = NULL;
    FILE *file = fopen(filepath, "r");
    if (!file) {
        return NULL;
    }
    word_array = malloc(sizeof(char *));
    if (!word_array) {
        return NULL;
    }
    word_array[0] = NULL;
    fill_from_file(&word_array, file);
    fclose(file);
    return word_array;
}

int main (int argc, char **argv)
{
    char **file = my_load_file_to_word_array(argv[1]);
    my_put_str_arr(file, 1);
    my_free_word_array(file);
    return 0;
}

测试文件与运行结果

测试文件内容(标注换行符和结束符以便查看):

My name is Saul.\n
I am Saul Goodman.\n
Better call Saul.\0

运行结果(末尾多了一行空行):

My name is Saul.
I am Saul Goodman. 
Better call Saul.
(此处为空行)

问题原因

问题源于getline()的行为和空行处理逻辑:

  • 当文件末尾存在换行符(或空行)时,getline()会读取到仅包含\n的行,返回的line_size为1。
  • 原代码中append_word_array会将这行的\n替换为\0,导致二维数组中多了一个空字符串。
  • 最终my_put_str_arr会为这个空字符串输出一个换行,形成多余的空行。

修复方案

方案1:在append_word_array中过滤空字符串

修改append_word_array函数,处理换行符后检查是否为空字符串,为空则不添加到数组:

void append_word_array(char ***array, char *line)
{
    size_t len = strlen(line);
    // 处理换行符并更新长度
    if (len > 0 && line[len - 1] == '\n') {
        line[len - 1] = '\0';
        len--;
    }
    // 过滤空字符串,不添加到数组
    if (len == 0) {
        return;
    }
    size_t array_len = 0;
    while ((*array)[array_len] != NULL) {
        array_len++;
    }
    (*array)[array_len] = strdup(line);
    (*array) = realloc((*array), (array_len + 2) * sizeof(char *));
    (*array)[array_len + 1] = NULL;
}

方案2:在fill_from_file中提前过滤空行

在读取行后直接判断是否为仅含换行符的空行,跳过这类行的处理:

void fill_from_file(char ***array, FILE *file)
{
    char *line_buff = NULL;
    size_t line_buff_size = 0;
    ssize_t line_size = getline(&line_buff, &line_buff_size, file);
    while (line_size >= 0) {
        // 跳过仅含换行符的空行
        if (line_size == 1 && line_buff[0] == '\n') {
            free(line_buff);
            line_buff = NULL;
            line_size = getline(&line_buff, &line_buff_size, file);
            continue;
        }
        append_word_array(array, line_buff);
        free(line_buff);
        line_buff = NULL;
        line_size = getline(&line_buff, &line_buff_size, file);
    }
    free(line_buff);
}

修复效果

两种方案都能过滤掉文件中的空行(包括末尾的空行),避免二维数组中出现空字符串,最终my_put_str_arr输出时不会产生多余的空行。

内容的提问来源于stack exchange,提问作者Nayrosk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 04:55:17