C语言实现标准输入文本读取到动态数组/链表并打印的问题求解
C语言文本读取打印程序问题修复方案
核心问题
- 指针传值错误:
readText函数接收一级指针,函数内修改pointer是局部变量,不会同步到main函数的原指针,导致realloc后原指针变成野指针,超过120字符就崩溃。 realloc用法错误:realloc会自动释放旧内存块,代码中额外调用free(pointer)会造成双重释放,触发内存错误。- 输入缓冲区残留:
scanf读取用户选择的数字后,缓冲区遗留换行符,会被第一次getchar读取并跳过,导致首字符丢失。 - 结束标记错误:将
EOF写入字符数组,打印时用*(char*)pointer != EOF判断结束是无效的,EOF是int类型值,超出char存储范围。 - 逻辑冗余错误:
realloc后手动偏移指针的逻辑错误,会导致数组越界访问。
修复步骤
- 修改函数原型:将
readText的第一个参数改为二级指针void **,支持修改外部传入的指针本身。 - 清理输入缓冲区:读取用户选择后,清空缓冲区残留的换行符,避免影响后续文本读取。
- 修正
realloc逻辑:删除free(pointer)调用,realloc成功后直接将新地址赋值给原指针。 - 调整结束逻辑:读取到
EOF后直接退出循环,在数组末尾添加'\0'作为字符串结束标记,打印时以此为结束判断条件。 - 优化打印逻辑:按每60字符换行,不足60的末尾行正常输出,避免多打印空行。
- 补充链表模式的读写实现,符合需求要求。
完整修正代码
/* 程序功能:从标准输入读取文本,选择动态数组或链表存储,按每行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
相关产品推荐
相关产品推荐

