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

C语言中从STDIN读取字符串存入char*数组为何仅保留最后一行?

问题:C语言getline读取行存入数组后,所有元素显示为最后一行内容

场景重现

输入文件内容:

T4
T2
T1
T1
S9
T5
S1
T1
T1
T1

使用的代码:

char *line = NULL;
size_t len = 0;
ssize_t lineSize = 0;
char* transactions[250];

int i = 0;
while((lineSize = getline(&line, &len, stdin)) != -1) {
    printf("You entered %s, which has %zu chars.\n", line, lineSize - 1);
    transactions[i] = line;
    printf("Added in %s\n", transactions[i]);
    i++;
}

printf("\n\n");
for (int j = 0; j < i; j++) {
    printf("transaction[%d] = %s\n", j, transactions[j]);
}

free(line);

程序输出:

my_shell>./prod 12 2 < inputexample.txt
nthreads: 12
id: 2
You entered T4
, which has 3 chars.
Added in T4

You entered T2
, which has 3 chars.
Added in T2

You entered T1
, which has 3 chars.
Added in T1

You entered T1
, which has 3 chars.
Added in T1

You entered S9
, which has 3 chars.
Added in S9

You entered T5
, which has 3 chars.
Added in T5

You entered S1
, which has 3 chars.
Added in S1

You entered T1
, which has 3 chars.
Added in T1

You entered T1
, which has 3 chars.
Added in T1

You entered T1, which has 1 chars.
Added in T1


transaction[0] = T1
transaction[1] = T1
transaction[2] = T1
transaction[3] = T1
transaction[4] = T1
transaction[5] = T1
transaction[6] = T1
transaction[7] = T1
transaction[8] = T1
transaction[9] = T1

问题点:while循环中能正确显示每行内容,但后续for循环里所有数组元素都变成了最后一行的内容。

原因分析

核心问题是所有数组元素都指向了同一块内存地址。

getline函数的工作逻辑是:当传入的line指针为NULL时,它会自动分配一块内存存储读取到的行;如果后续读取的行长度不超过已分配的内存大小(len变量记录),它会复用这块内存,直接把新行的内容覆盖进去。

你的代码中,每次循环都把line指针赋值给transactions[i],相当于让数组里的每个元素都指向同一块内存空间。当getline读取下一行时,会覆盖这块内存里的旧内容,最后所有元素自然都指向最后一行的内容。

while循环里能正确显示,是因为每次赋值后立刻打印,此时内存里的内容还没被下一次的getline覆盖。

解决方案

需要为每行内容单独分配内存,把getline读取到的内容复制一份存起来,而不是直接复用line指针。以下两种方法均可实现:

方法1:使用strdup

修改while循环内的赋值语句:

transactions[i] = strdup(line);

strdup会自动分配足够的内存,复制line里的内容并返回新指针。注意最后要逐个释放数组里的每个元素,再释放line。

方法2:手动内存分配

如果环境不支持strdup,可以手动实现内存分配与复制:

// 分配对应大小的内存,lineSize包含换行符和终止符的长度
transactions[i] = malloc(lineSize);
if (transactions[i] != NULL) {
    strcpy(transactions[i], line);
}

修改后的完整代码示例

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

int main() {
    char *line = NULL;
    size_t len = 0;
    ssize_t lineSize = 0;
    char* transactions[250];

    int i = 0;
    while((lineSize = getline(&line, &len, stdin)) != -1) {
        printf("You entered %s, which has %zu chars.\n", line, lineSize - 1);
        // 复制内容到新分配的内存
        transactions[i] = strdup(line);
        printf("Added in %s\n", transactions[i]);
        i++;
    }

    printf("\n\n");
    for (int j = 0; j < i; j++) {
        printf("transaction[%d] = %s\n", j, transactions[j]);
    }

    // 释放数组里的每个元素
    for (int j = 0; j < i; j++) {
        free(transactions[j]);
    }
    free(line);
    return 0;
}

修改后,数组里的每个元素都指向独立的内存块,存储各自的行内容,后续遍历就不会出现全部显示最后一行的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 18:01:25