如何从二进制文件中写入和读取动态数组

时间:2018-07-05 16:28:20

标签: c struct binaryfiles dynamic-arrays

我有这个结构

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

我想将所有数据复制到二进制文件中。 首先,我已经为成分和过程动态分配了内存,并编写了所需的全部内容。但是然后我需要将所有内容都写入一个二进制文件中。我知道它们都是指针,所以这意味着如果我使用

fwrite(&recipe,sizeof(recipe),1,fbr);

我将在文件中写入地址,而不是我需要的实际值。我尝试用这种方式将struct的每个字段写入文件

    fwrite(recipe.name,sizeof(recipe.name),1,fbr);

    fgets(recipe.ingredients[j],30,stdin);
            strcpy(buff,recipe.ingredients[j]);
            len = strlen(buff);
            fwrite(buff,sizeof(recipe.ingredients[0]),len,fbr);

   fwrite(recipe.diff,sizeof(recipe.diff),1,fbr);
   fwrite(&recipe.time,sizeof(recipe.time),1,fbr);
   fwrite(&recipe.calories,sizeof(recipe.calories),1,fbr);

    fgets(recipe.procedure[i],1000,stdin);
            strcpy(buff,recipe.procedure[i]);
            len = strlen(buff);
            fwrite(buff,sizeof(recipe.procedure[0]),len,fbr);

我不确定这是正确的方法,但是我尝试将字符串放入另一个字符串中,然后将其复制到文件中。问题是,我不确定它是否有效,因为我不知道应该使用哪种命令读取存储的所有值。以它的名字当然有效,我对此没有任何问题,但是当我要阅读成分时,我封锁了自己,因为我在另一个字符串中写了该值,而且我不知道应该输入多少长度阅读。也许我缺少了一些东西,也许我一开始就很在意写作,但此时我不知道该怎么办。

2 个答案:

答案 0 :(得分:0)

您想要执行以下操作来写出您的食谱:

    fwrite(recipe.name,sizeof(recipe.name),1,fbr);
    for (int i = 0; i < num_ingredients; i++) {
            int len = strlen(recipe.ingredients[i]) + 1;
            int num_elements = fwrite(recipe.ingredients[i],sizeof(char),len,fbr);
            printf("wrote %d elements for %s\n", num_elements, recipe.ingredients[i]);
    }
    fwrite(recipe.diff,sizeof(recipe.diff),1,fbr);
    for (int i = 0; i < num_procedures; i++) {
            int len = strlen(recipe.procedure[i]) + 1;
            int num_elements = fwrite(recipe.procedure[i],sizeof(char),len,fbr);
            printf("wrote %d elements for %s\n", num_elements, recipe.procedure[i]);
    }

当然,您还需要写出卡路里和时间。在将任何内容读入struct之前,我也会这样做:

memset(&recipe, 0, sizeof(struct _recipe));

如果您使用fprintf用\n来写出卡路里和时间,并使用分隔符,则配方文件将如下所示:

$ od -c recipe.bin
0000000   m   u   f   f   i   n   s  \0  \0  \0  \0  \0  \0  \0  \0  \0
0000020  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
*
0000060  \0  \0   f   l   o   u   r  \0   s   u   g   a   r  \0   e   g
0000100   g   s  \0   v   a   n   i   l   l   a  \0   n   u   t   s  \0
0000120   n   o       d   i   f   f  \0  \0  \0  \0  \0   m   i   x  \0
0000140   b   a   k   e  \0   r   e   s   t  \0   6   0  \n   2   5   0
0000160  \n

答案 1 :(得分:0)

您可以设计一个简单的存储protocol来进行读写。

例如:

| struct recipe | t l v | t l v | ... | t l v | struct recipe | t l v | ... | t l v |

|<-      a complete struct recipe data      ->|


| description | t(ype) | l(ength) | v(alue)|
| ingredient  | i      | strlen() | string |
| procedure   | p      | strlen() | string |
| data end    | e      | 0        | <null> |

读取配方数据:

1. Read a struct recipe.
2. Read a t, t=='i' -- go (3.), t=='p' -- go (4.), t=='e' -- go (5.).
3. Read a l, then read a string whose length is l as an ingredient. Go (2.).
4. Read a l, then read a string whose length is l as a procedure. Go (2.).
5. Finish.

写入配方数据:

1. Write a struct recipe.
2. Write ingredients to `i strlen(ingredient) ingredient` one by one.
3. Write procedures to `p strlen(procedure) procedure` one by one.
4. Write `e 0`.
5. Finish.

伪代码:(只是一个演示,请设计自己的protol-

void write_recipe(recipe *r, FILE *fp)
{
    fwrite(r, sizeof(recipe), 1, fp);
    // ...
    for ()
    {
        sprintf(buff, "i %5d %s", strlen(r->ingredients[i]), r->ingredients[i]);
        fwrite(buff, strlen(buff), 1, fp);
    }
    sprintf(buff, "e 0");
    fwrite(buff, strlen(buff), 1, fp);
    //...
    for ()
    {
        sprintf(buff, "p %5d %s", strlen(r->procedure[i]), r->procedure[i]);
        fwrite(buff, strlen(buff), 1, fp);
    }
    sprintf(buff, "e 0");
    fwrite(buff, strlen(buff), 1, fp);
    // ...
}

void read_recipe(FILE *r, FILE *fp)
{
    fread(r, sizeof(recipe), 1, fp);
    // ...
    while (true)
    {
        fread(&t, sizeof(char), 1, fp);
        if (t == 'e')
        {
            // ...
            break;
        }
        fread(buff, sizeof(char), 7, fp);
        sscanf("%d", &len);
        fread(buff, sizeof(char), len, fp);
        buff[len] = 0;

        ingredient = malloc(sizeof(char) * (len + 1));
        strcpy(ingredient, buff);
        // ...
    }
    // ...
    while (true)
    {
        fread(&t, sizeof(char), 1, fp);
        if (t == 'e')
        {
            // ...
            break;
        }
        fread(buff, sizeof(char), 7, fp);
        sscanf("%d", &len);
        fread(buff, sizeof(char), len, fp);
        buff[len] = 0;

        procedure = malloc(sizeof(char) * (len + 1));
        strcpy(procedure, buff);
        // ...
    }
    // ...
}