【问题标题】:How to manage a dynamic array of strings in C如何在 C 中管理字符串的动态数组
【发布时间】:2018-07-04 21:40:51
【问题描述】:

我有一个代表食谱的结构。我不知道如何处理成分和程序,因为我首先不知道存储所有信息需要多少内存。 我以这种方式初始化了结构

struct _recipe
{
    char name[50];
    char** ingredients;
    char diff[12];
    int time;
    int calories;
    char** procedure;   
} recipe;

我尝试用这种方式分配它们两个

recipe.ingredients = malloc(sizeof(char*) * 50);
recipe.procedure = malloc(sizeof(char*) * 50);

for(i = 0; i < 50; i++)
{
    recipe.ingredients[i] = malloc(sizeof(char) * 30);
    recipe.procedure[i] = malloc(sizeof(char) * 500);
}

但是在我尝试在其中写入后,我得到了一个奇怪的输出。在打印出字符串后,我在进程结束时释放了内存,但我的程序有一个奇怪的行为,很可能是因为我遇到了分段错误,但我不明白为什么。那是因为我以错误的方式分配内存吗? 在我结束这个过程后,它说返回值为 1。

这就是我取消引用指针的方式

for(i = 50; i >= 0; i--){
    free(recipe.ingredients[i]);
}

for(j = 50; j >= 0; j--)
{
    free(recipe.procedure[j]);
}
free(recipe.ingredients);
free(recipe.procedure);

在我尝试放置一个计数器来记住我使用了多少内存并且只释放未使用的内存后,我得到了这个输出

Apple pie
pø└
pø└
P└
P└
P└
PÃ└
PÃ└
PÃ└
PÃ└
└ÿc
└ÿc
└ÿc
pø└
pø└




































Easy
60 min
230 kcal
Mix milk and flour

P└
Bake them

P└
P└
P└
P└
P└
P└
P└
P└
P└
P└
P└
└ÿc
└ÿc
└ÿc

我知道我使用计数器以一种不好的方式取消引用,但是如果我编辑并取消引用所有 50 个元素,程序就会崩溃。无论如何,为了得到这个结果,我把它放在输入中: -名称:苹果派 材料:苹果 糖 面粉 牛奶 难度:简单 以分钟为单位的时间(准备):60 卡路里:230 程序:将牛奶和面粉混合 添加苹果 烤它们 该过程返回 1。我知道这是描述食谱的一种可怕方式,我只是在输入中输入了几个字符串来显示它是如何结束的

这是我所有的代码,我不知道如何摆脱错误

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    struct _recipe
{
    char name[50];
    char** ingredients;
    char diff[12];
    int time;
    int calories;
    char** procedure;   
} recipe;
    int i = 0;
    int j = 0;
    char sentinel[] = "yes";
    char stop[] = "yes";
    char space = '\n';
    int counter = 0;
    int total = 0;
recipe.ingredients = malloc(sizeof(char*) * 50);
recipe.procedure = malloc(sizeof(char*) * 50);

for(i = 0; i < 50; i++)
{
    recipe.ingredients[i] = malloc(sizeof(char) * 30);
    recipe.procedure[i] = malloc(sizeof(char) * 500);
}


        printf("Put the name of recipe:\n");
        fgets(recipe.name,30,stdin);
        do{
            printf("Put the ingredient:\n");
            fgets(recipe.ingredients[j],30,stdin);
            j++;
            counter++;
            printf("Do you want to continue? (yes/no)");
            gets(sentinel);
        } while(strcmp("yes",sentinel) == 0);


        printf("Put difficulty (Easy Medium Hard):\n");
        fgets(recipe.diff,11,stdin);
        printf("Put time for preparation(in minutes):\n");
        scanf("%d", &recipe.time);
        space = getchar();
        printf("Inserisci l'apporto calorico:\n");
        scanf("%d", &recipe.calories);
        space = getchar();
        i = 0;
        do{
            printf("Put the procedure:\n");
            fgets(recipe.procedure[i],1000,stdin);
            i++;
            total++;
            printf("Do you want to continue? (yes/no)\n");
            gets(stop);
        } while(strcmp("yes", stop) == 0);





        printf("%s", recipe.name);
        for(i = 0; i < counter; i++)
        {
            printf("%s", recipe.ingredients[i]);
        }
        printf("%s\n", recipe.diff);
        printf("%d min\n", recipe.time);
        printf("%d kcal\n", recipe.calories);
        for (j = 0; j < total; j++)
        {
            printf("%s", recipe.procedure[j]);
        }

            for(i = 49; i >= 0; i--){
        free(recipe.ingredients[i]);
    }

    for(j = 49; j >= 0; j--)
    {
        free(recipe.procedure[j]);
    }
    free(recipe.ingredients);
    free(recipe.procedure);
    return 0;
}

【问题讨论】:

  • 您发布的代码是正确的。问题必须出在写入它们的其他代码中。你应该使用类似strcpy(recipe.ingredients[i], some_ingredient);
  • @Barmar 所以我应该创建另一个字符串,将字符串放入其中,这样我就不会出现内存泄漏之类的问题?对不起,如果我无知,我是使用动态内存的新手
  • 显示填写食谱的代码,这就是您的问题所在。
  • fgets(recipe.ingredients[j], 30, stdin); 应该可以工作。请提供一个minimal reproducible example 来证明您遇到的问题。
  • @Goner 取消引用指针和释放分配的内存是两个完全不同的事情。但我们需要更多代码才能找到您的问题,请发帖MCVE

标签: c arrays pointers segmentation-fault malloc


【解决方案1】:

您的代码是正确的,也许是您取消引用的方式?

以下作品:

 for(int i = 0; i < 50; i++)
    {
        for(int j = 0; j < 30; j++){
            recipe.ingredients[i][j] = 'a';
        }
    }
printf("Hello %c", recipe.ingredients[3][4]);

如果您发布取消引用的代码,那么我们可以进一步帮助您。

【讨论】:

  • 请不要猜测答案。而是等待澄清。如果你有声望,请发表评论。
  • 我知道这种方式可行,但我正在做一个学校项目,我更喜欢学习使用动态内存,但感谢您的回答
  • 上面的例子是动态内存的,我用你的代码和 malloc 调用。
猜你喜欢
  • 1970-01-01
  • 2015-03-09
  • 1970-01-01
  • 1970-01-01
  • 2017-08-27
  • 2019-04-18
  • 1970-01-01
  • 1970-01-01
  • 2015-09-24
相关资源
最近更新 更多