C语言新手求助:如何将字符串存入多维数组及指针数组?
解决字符串存储的两种实现方式:多维数组 & 指针数组
Hey there! 作为C语言新手,你已经迈出了不错的第一步,但现有代码里有几个关键问题需要调整,我们先理清楚,再一步步实现两种要求的方式。
先分析你现有代码的问题
你的尝试代码里有几个明显的bug:
char str[x];只是一个一维数组,每次输入新字符串都会覆盖之前的内容,没法存储多个字符串- 循环里的
char arr[j];是局部变量,每次循环都会被销毁,而且arr[j] = str[x];是越界访问(str的有效索引是0到x-1),也没有给字符串加终止符'\0',用printf("%s", arr)会导致未定义行为 - 没有考虑字符串的终止符
'\0',C语言里字符串必须以这个字符结尾,所以定义数组时要多留一个位置
方式一:用多维数组存储每行一个字符串
多维数组的思路是创建一个二维数组,第一维代表字符串的数量,第二维代表每个字符串的最大长度(要包含终止符)。下面是修正后的完整代码:
#include <stdio.h> int main(){ int n; // 字符串数量 int max_len; // 每个字符串的最大字符数(不含终止符) printf("How many strings do you want to insert? "); scanf("%d", &n); if (n < 1 || n > 20) { printf("Error: the number must be between 1 and 20\n"); return 1; } printf("What's the maximum number of characters per string? "); scanf("%d", &max_len); if (max_len > 10) { printf("Error: the number of characters must be <= 10\n"); return 1; } // 定义二维数组,每个字符串预留max_len+1的空间(+1存'\0') char str_arr[n][max_len + 1]; // 清除scanf留下的换行符,避免影响后续输入 getchar(); for(int i = 0; i < n; i++){ printf("Insert string %d: ", i+1); // 用fgets读取整行,包括空格,同时限制长度 fgets(str_arr[i], max_len + 1, stdin); // 去掉fgets读取到的换行符(如果存在) char *newline = str_arr[i]; while (*newline != '\0') { if (*newline == '\n') { *newline = '\0'; break; } newline++; } } // 打印存储的所有字符串 printf("\nAll stored strings:\n"); for(int i = 0; i < n; i++){ printf("String %d: %s\n", i+1, str_arr[i]); } return 0; }
关键说明:
- 二维数组
str_arr[n][max_len+1]:n是字符串个数,max_len+1是每个字符串的长度(包含终止符) - 用
fgets代替scanf("%s"):可以读取包含空格的字符串,更符合“每行一个字符串”的需求 - 处理换行符:
fgets会把输入时的换行符也读进来,所以要手动替换成'\0',保证字符串格式正确
方式二:用指针数组存储字符串
指针数组的思路是创建一个数组,每个元素都是char*类型的指针,指向单独分配的内存块(用来存每个字符串)。这种方式的优势是如果每个字符串长度不一样,可以节省内存,也更灵活。
下面是完整实现代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(){ int n; int max_len; printf("How many strings do you want to insert? "); scanf("%d", &n); if (n < 1 || n > 20) { printf("Error: the number must be between 1 and 20\n"); return 1; } printf("What's the maximum number of characters per string? "); scanf("%d", &max_len); if (max_len > 10) { printf("Error: the number of characters must be <= 10\n"); return 1; } // 定义指针数组,每个元素是char* char *str_ptrs[n]; getchar(); // 清除换行符 for(int i = 0; i < n; i++){ // 为每个字符串分配内存,max_len+1存终止符 str_ptrs[i] = (char*)malloc((max_len + 1) * sizeof(char)); if (str_ptrs[i] == NULL) { printf("Memory allocation failed!\n"); // 如果分配失败,要释放已经分配的内存 for(int j = 0; j < i; j++){ free(str_ptrs[j]); } return 1; } printf("Insert string %d: ", i+1); fgets(str_ptrs[i], max_len + 1, stdin); // 替换换行符为'\0' char *newline = str_ptrs[i]; while (*newline != '\0') { if (*newline == '\n') { *newline = '\0'; break; } newline++; } } // 打印存储的字符串 printf("\nAll stored strings:\n"); for(int i = 0; i < n; i++){ printf("String %d: %s\n", i+1, str_ptrs[i]); } // 记得释放动态分配的内存,避免内存泄漏 for(int i = 0; i < n; i++){ free(str_ptrs[i]); } return 0; }
关键说明:
char *str_ptrs[n]:这是一个指针数组,每个元素指向一个字符串的起始地址malloc动态分配内存:每个字符串单独分配内存,用完后必须用free释放,否则会造成内存泄漏- 内存分配失败的处理:如果
malloc返回NULL,要释放已经分配的内存,避免泄漏
内容的提问来源于stack exchange,提问作者Schiele




