You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动