C语言中如何将字符串存入字符指针数组?及异常问题排查
问题排查与解决方案
嘿,这问题我太熟了!你这是踩了C语言里局部变量内存生命周期的大坑啦。咱们一步步拆解:
问题根源
你在init_NFA_table函数里定义的char input[]是栈上的局部变量,它的内存空间只有在函数执行时才有效,函数结束后这块内存会被系统回收(或者被后续操作覆盖)。更关键的是:
- 如果是在循环中重复使用这个
input数组读取输入,每次循环都会复用同一块栈内存; - 你把
input的地址直接赋值给NFAtab[x][y],导致所有指针数组的元素都指向了同一块内存区域; - 最后这块内存里留存的是你最后一次输入的字符串,所以打印时所有位置都显示最后那个值。
举个错误代码的典型例子(对应你遇到的场景):
char *NFAtab[STATES][SYMBOLS]; void init_NFA_table() { char input[20]; // 局部栈数组,每次循环复用同一块内存 for (int x = 0; x < STATES; x++) { for (int y = 0; y < SYMBOLS; y++) { scanf("%s", input); NFAtab[x][y] = input; // 错误:所有元素指向同一个地址 } } }
三种解决方案
1. 动态分配内存(最灵活)
每次读取输入后,用strdup()(或malloc+strcpy)复制字符串到新分配的堆内存中,把新内存的地址赋值给指针数组元素。这样每个元素都有独立的内存空间,不会互相影响。
示例代码:
#include <string.h> // 包含strdup所需头文件 #include <stdlib.h> // 包含malloc/free所需头文件 char *NFAtab[STATES][SYMBOLS]; void init_NFA_table() { char input[20]; for (int x = 0; x < STATES; x++) { for (int y = 0; y < SYMBOLS; y++) { scanf("%s", input); // 用strdup复制字符串,自动分配内存 NFAtab[x][y] = strdup(input); // 或者手动malloc+strcpy(兼容性更好) // size_t len = strlen(input) + 1; // NFAtab[x][y] = malloc(len); // if (NFAtab[x][y] != NULL) { // strcpy(NFAtab[x][y], input); // } } } } // 记得在程序结束前释放内存,避免泄漏 void free_NFA_table() { for (int x = 0; x < STATES; x++) { for (int y = 0; y < SYMBOLS; y++) { free(NFAtab[x][y]); } } }
2. 使用二维字符数组(最省心)
如果你能提前确定字符串的最大长度,可以把NFAtab定义成二维字符数组,直接用strcpy复制字符串,避免指针操作的坑。
示例代码:
#define MAX_STR_LEN 20 // 根据你的需求调整长度 char NFAtab[STATES][SYMBOLS][MAX_STR_LEN]; void init_NFA_table() { char input[MAX_STR_LEN]; for (int x = 0; x < STATES; x++) { for (int y = 0; y < SYMBOLS; y++) { scanf("%s", input); strcpy(NFAtab[x][y], input); // 直接复制字符串到数组元素 } } }
注意:要确保MAX_STR_LEN足够大,避免字符串截断或缓冲区溢出。
3. 使用静态数组(不推荐,仅特殊场景)
把input定义成static char input[],这样它的内存会放在静态存储区,函数结束后不会被释放。但要注意:静态数组每次循环还是会被覆盖,所以如果是多次读取输入,还是会出现后续值覆盖之前的情况,只有单次赋值时适用,灵活性很差。
关键提醒
- 用动态分配内存时,一定要记得在程序结束前调用
free释放内存,否则会造成内存泄漏; - 如果使用
strdup,要确认你的编译环境支持(大部分POSIX系统都支持,Windows下可能需要自行实现); - 用二维字符数组时,务必预留足够的空间存储字符串结束符
\0。
内容的提问来源于stack exchange,提问作者raultds
相关产品推荐
相关产品推荐

