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

C语言实现标准输入文本读取到动态数组/链表并打印的问题求解

C语言文本读取打印程序问题修复方案

核心问题

  • 指针传值错误:readText函数接收一级指针,函数内修改pointer是局部变量,不会同步到main函数的原指针,导致realloc后原指针变成野指针,超过120字符就崩溃。
  • realloc用法错误:realloc会自动释放旧内存块,代码中额外调用free(pointer)会造成双重释放,触发内存错误。
  • 输入缓冲区残留:scanf读取用户选择的数字后,缓冲区遗留换行符,会被第一次getchar读取并跳过,导致首字符丢失。
  • 结束标记错误:将EOF写入字符数组,打印时用*(char*)pointer != EOF判断结束是无效的,EOF是int类型值,超出char存储范围。
  • 逻辑冗余错误:realloc后手动偏移指针的逻辑错误,会导致数组越界访问。

修复步骤

  1. 修改函数原型:将readText的第一个参数改为二级指针void **,支持修改外部传入的指针本身。
  2. 清理输入缓冲区:读取用户选择后,清空缓冲区残留的换行符,避免影响后续文本读取。
  3. 修正realloc逻辑:删除free(pointer)调用,realloc成功后直接将新地址赋值给原指针。
  4. 调整结束逻辑:读取到EOF后直接退出循环,在数组末尾添加'\0'作为字符串结束标记,打印时以此为结束判断条件。
  5. 优化打印逻辑:按每60字符换行,不足60的末尾行正常输出,避免多打印空行。
  6. 补充链表模式的读写实现,符合需求要求。

完整修正代码

/* 程序功能:从标准输入读取文本,选择动态数组或链表存储,按每行60字符输出
 * 规则:
 * 1. 每行最多打印60个字符
 * 2. 内存不足时打印已存储的所有内容
 */

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

#define LINE_SIZE 60
#define BUFFER 1
#define LINKED_LIST 2

/* 函数原型修正,readText用二级指针修改外部指针 */
void readText(void **pointer, int dataStructType);
void printText(void *pointer, int dataStructType);

/* 链表结构体定义 */
struct linkedList
{
    char data[LINE_SIZE];
    struct linkedList *next;
};

int main()
{
    void *pointer = NULL;
    int dataStructType = 0;

    printf("请选择要使用的数据结构,输入对应编号按回车:\n1 - 动态数组\n2 - 链表\n");
    scanf("%d", &dataStructType);

    /* 清空输入缓冲区残留的换行 */
    while(getchar() != '\n');

    /* 输入校验 */
    while(dataStructType != BUFFER && dataStructType != LINKED_LIST)
    {
        printf("输入无效!请重新输入:\n1 - 动态数组\n2 - 链表\n");
        scanf("%d", &dataStructType);
        while(getchar() != '\n');
    }

    if(dataStructType == BUFFER)
    {
        printf("您选择了:动态数组\n");
        pointer = (char*) calloc(LINE_SIZE, sizeof(char));
        if(!pointer)
        {
            printf("错误:内存分配失败,请稍后重试\n");
            return 0;
        }
        /* 传指针的地址给readText */
        readText(&pointer, dataStructType);
        printText(pointer, dataStructType);
        /* 释放动态数组内存 */
        free(pointer);
    }
    else
    {
        printf("您选择了:链表\n");
        struct linkedList *head = NULL;
        head = calloc(1, sizeof(struct linkedList));
        if(!head)
        {
            printf("错误:内存分配失败,请稍后重试\n");
            return 0;
        }
        pointer = head;
        readText(&pointer, dataStructType);
        printText(pointer, dataStructType);
        /* 释放链表内存 */
        struct linkedList *temp;
        while(head != NULL)
        {
            temp = head;
            head = head->next;
            free(temp);
        }
    }
    return 0;
}

void readText(void **pointer, int dataStructType)
{
    int cnt = 0;
    int currentCell = 0;
    char c;
    int lines = 1;
    char *holder = NULL;
    printf("请输入文本,输入完成后按Ctrl+D结束:\n");

    if(dataStructType == BUFFER)
    {
        char *buf = (char *)*pointer;
        while((c = getchar()) != EOF)
        {
            if(c == '\n')
                continue;
            if(cnt == LINE_SIZE)
            {
                cnt = 0;
                lines++;
                holder = (char *)realloc(buf, lines * LINE_SIZE * sizeof(char));
                if(holder == NULL)
                {
                    printf("错误:内存分配失败,将打印已收集的文本\n");
                    buf[currentCell] = '\0';
                    *pointer = buf;
                    printText(*pointer, BUFFER);
                    return;
                }
                /* realloc自动释放旧内存,不需要手动free */
                buf = holder;
            }
            buf[currentCell++] = c;
            cnt++;
        }
        /* 添加结束标记 */
        buf[currentCell] = '\0';
        *pointer = buf;
    }
    else
    {
        struct linkedList *current = (struct linkedList *)*pointer;
        while((c = getchar()) != EOF)
        {
            if(c == '\n')
                continue;
            if(cnt == LINE_SIZE)
            {
                cnt = 0;
                current->next = calloc(1, sizeof(struct linkedList));
                if(current->next == NULL)
                {
                    printf("错误:内存分配失败,将打印已收集的文本\n");
                    current->data[cnt] = '\0';
                    printText(*pointer, LINKED_LIST);
                    return;
                }
                current = current->next;
            }
            current->data[cnt++] = c;
        }
        current->data[cnt] = '\0';
    }
}

void printText(void *pointer, int dataStructType)
{
    if(dataStructType == BUFFER)
    {
        char *buf = (char *)pointer;
        int cnt = 0;
        while(*buf != '\0')
        {
            putchar(*buf);
            cnt++;
            buf++;
            if(cnt == LINE_SIZE)
            {
                putchar('\n');
                cnt = 0;
            }
        }
        /* 最后一行不足60字符也补换行 */
        if(cnt != 0)
            putchar('\n');
    }
    else
    {
        struct linkedList *current = (struct linkedList *)pointer;
        int cnt = 0;
        while(current != NULL)
        {
            char *p = current->data;
            while(*p != '\0' && cnt < LINE_SIZE)
            {
                putchar(*p);
                cnt++;
                p++;
                if(cnt == LINE_SIZE)
                {
                    putchar('\n');
                    cnt = 0;
                }
            }
            current = current->next;
        }
        if(cnt != 0)
            putchar('\n');
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 07:57:01