如何将字符串复制到动态二维数组?代码问题排查
可行,但你的代码存在多个严重问题
首先明确:通过getchar()流式读取输入并存储到二维字符串数组是完全可行的,但你的代码有不少致命bug,以下是具体问题和修复方案:
核心问题
- 类型错误:你定义的
char *arr是单个字符的指针,但要存储字符串数组(二维字符数组),必须用char **arr(指向指针的指针)。当前代码中arr[counter_str - 1] = malloc(...)是把指针赋值给char类型变量,会截断地址,直接导致内存访问错误。 - 变量类型错误:
getchar()返回int类型(需容纳EOF这个特殊值),你把sym定义为char,如果系统中char是无符号类型,sym永远不会等于EOF,循环会无限执行。 - 缓冲区溢出:
string[50]的大小是固定的,但你没有检查counter是否超过数组上限(最多49,因为要留位置给终止符),一旦输入的单行内容过长,会越界写入,引发未定义行为。 - 未处理EOF结尾的行:如果输入不是以换行符结束(比如直接按Ctrl+D/Ctrl+Z触发EOF),最后一行的内容根本不会被存入数组,因为只有遇到
\n才会执行存储逻辑。 - realloc风险:直接把
realloc的结果赋值给arr,如果内存分配失败返回NULL,会丢失原来的内存地址,造成内存泄漏。 - 内存泄漏:程序结束前没有释放
arr和每个字符串占用的内存,虽然程序退出后系统会回收,但这是不良编程习惯。 - 逻辑判断错误:原代码第一个if的括号位置有误,
(sym != ' ') && (sym != (' ') && (sym != '\n'))的逻辑会变成先判断sym != '\t' && sym != '\n',再和sym != ' '做与运算,写法冗余且易混淆,应简化为sym != ' ' && sym != '\t' && sym != '\n'。
修复后的代码示例
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_LINE_LEN 50 int main() { char **arr = NULL; // 改为指向指针的指针 char string[MAX_LINE_LEN]; int sym; // 改为int类型以容纳EOF int counter = 0; int counter_str = 0; while((sym = getchar()) != EOF) { // 检查缓冲区是否已满,留出位置给终止符 if (counter >= MAX_LINE_LEN - 1) { fprintf(stderr, "行内容过长,截断处理\n"); // 跳过当前行剩余字符 while ((sym = getchar()) != EOF && sym != '\n'); counter = 0; continue; } if(sym != ' ' && sym != '\t' && sym != '\n'){ string[counter] = sym; counter++; } // 处理换行或EOF结尾的非空行 if((sym == '\n') || (sym == EOF && counter > 0)){ string[counter] = '\0'; // 若要保留换行符,可改为string[counter++] = '\n'; string[counter] = '\0'; // 先将realloc结果存入临时变量,避免内存丢失 char **temp = realloc(arr, (counter_str + 1) * sizeof(char*)); if (!temp) { fprintf(stderr, "内存分配失败\n"); // 释放已分配的内存 for (int i = 0; i < counter_str; i++) { free(arr[i]); } free(arr); return 1; } arr = temp; // 为当前行分配内存 arr[counter_str] = malloc(strlen(string) + 1); if (!arr[counter_str]) { fprintf(stderr, "内存分配失败\n"); // 释放已分配内存 for (int i = 0; i < counter_str; i++) { free(arr[i]); } free(arr); return 1; } strcpy(arr[counter_str], string); counter_str++; counter = 0; } } // 测试输出存储的内容 printf("存储的%d行内容:\n", counter_str); for (int i = 0; i < counter_str; i++) { printf("%s\n", arr[i]); free(arr[i]); // 释放每个字符串的内存 } free(arr); // 释放指针数组的内存 return 0; }
额外说明
- 修复后的代码加入了内存分配失败的错误处理,避免程序崩溃或内存泄漏。
- 如果需要保留每行的换行符,可调整终止符的赋值逻辑,把换行符加入
string后再添加'\0'。
内容的提问来源于stack exchange,提问作者Ho1j
相关产品推荐
相关产品推荐

