我的删除功能会删除错误的struct记录

时间:2018-07-10 22:56:50

标签: c struct binaryfiles

我具有此功能,该功能应删除用户请求的配方。我总是以这种方式删除记录,但是我不知道为什么这次不能以正确的方式工作。有时它指出没有匹配项,但是会删除配方或删除文件中的所有配方,但我不明白为什么,因为我基本上创建了一个临时文件,在其中写入除用户想要的记录以外的所有记录删除,并且我使用了一个用于其他记录的函数,所以我真的不明白。那是因为所有食谱的配料长度和步骤都不一样吗?

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

int stringCmpi (char *s1,char *s2);

struct _recipe
{
    char name[40];
    int count_i;
    char ingredients[20][40];
    char diff[12];
    int timr;
    int calories;
    int count_p;
    char procedure[30][500];
} recipe;

int main()
{
    FILE* fbr;
    FILE* temp;
    char ricetta_name[] = "ricette.bin";
    char temp_name[] = "temp.bin";
    fbr = fopen("ricette.bin", "rb");
    temp = fopen("temp.bin", "wb");
    int found = 0;
    char name_t[40];
    int i;
    char space = '\n';

    if(fbr == NULL)
    {
       printf("Couldn't open the file.\n");
       exit(1);
    }
    if(fbr == NULL)
    {
       printf("Couldn't open the file.\n");
       exit(1);
    }


    printf("Write the name of the recipe you want to delete:\n");
    fgets(name_t,sizeof(name_t),stdin);
    space = getchar();
    while(fread(&recipe,sizeof(recipe),1,fbr) && found == 0)
    {   
        if(stringCmpi(name_t,recipe.name) == 0)
        {
            found = 1;
            printf("Match found. Recipe deleted.\n");
        }

        else
        {

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

        }
            if(!found)
    {
        printf("No match.\n");
    }
    }



    fclose(fbr);
    fclose(temp);
    remove(ricetta_name);
    rename(temp_name,ricetta_name);
    system("PAUSE");
    return 0;
}

int stringCmpi (char *s1,char *s2)
{
    int i=0;
    for(i=0; s1[i]!='\0'; i++)
    {
        if( toupper(s1[i])!=toupper(s2[i]) )
            return 1;           
    }
    return 0;
}

3 个答案:

答案 0 :(得分:1)

问题在这里:

Google Analytics

一旦找到配方,就退出循环,因此其余元素不会复制到新文件中。建议您删除while(fread(&recipe,sizeof(recipe),1,fbr) && found == 0) 子句。

此外:

&& found == 0

这实际上是在if(!found) { printf("No match.\n"); } 循环中,因此它将多次报告while。请把它移到循环之外。

答案 1 :(得分:1)

  1. 正确的缩进将帮助您查看程序的实际结构。这样发布的程序具有一致的缩进效果:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int stringCmpi (char *s1,char *s2);
    
    struct _recipe
    {
        char name[40];
        int count_i;
        char ingredients[20][40];
        char diff[12];
        int timr;
        int calories;
        int count_p;
        char procedure[30][500];
    } recipe;
    
    int main()
    {
        FILE* fbr;
        FILE* temp;
        char ricetta_name[] = "ricette.bin";
        char temp_name[] = "temp.bin";
        fbr = fopen("ricette.bin", "rb");
        temp = fopen("temp.bin", "wb");
        int found = 0;
        char name_t[40];
        int i;
        char space = '\n';
    
        if(fbr == NULL)
        {
            printf("Couldn't open the file.\n");
            exit(1);
        }
        if(fbr == NULL)
        {
            printf("Couldn't open the file.\n");
            exit(1);
        }
    
        printf("Write the name of the recipe you want to delete:\n");
        fgets(name_t,sizeof(name_t),stdin);
        space = getchar();
        while(fread(&recipe,sizeof(recipe),1,fbr) && found == 0)
        {
            if(stringCmpi(name_t,recipe.name) == 0)
            {
                found = 1;
                printf("Match found. Recipe deleted.\n");
            }
    
            else
            {
                fwrite(&recipe,sizeof(recipe),1,temp);
            }
            if(!found)
            {
                printf("No match.\n");
            }
        }
    
        fclose(fbr);
        fclose(temp);
        remove(ricetta_name);
        rename(temp_name,ricetta_name);
        system("PAUSE");
        return 0;
    }
    
    int stringCmpi (char *s1,char *s2)
    {
        int i=0;
        for(i=0; s1[i]!='\0'; i++)
        {
            if( toupper(s1[i])!=toupper(s2[i]) )
                return 1;
        }
        return 0;
    }
    
  2. 程序正在两次检查fbr是否不为NULL。可能第二次检查应该是temp

  3. 找到要删除的配方后,程序将停止读取和复制;这意味着以下记录不会被复制。

  4. 程序抱怨找不到每种配方,直到找到所需的配方。

建议:

  • 修改while循环条件以消除&& ! found,以便复制所有记录(匹配给定名称的记录除外)。

  • if (! found)的检查移到循环之外。

奖金:

  • 函数stringCmpi()在字符串s1的末尾停止比较;这意味着“ abc”和“ abcdef”将比较相等。您可能想将return 0更改为return s1 [i] != s2 [i]

答案 2 :(得分:0)

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

struct _recipe
{
    char name[40];
    int count_i;
    char ingredients[20][40];
    char diff[12];
    int timr;
    int calories;
    int count_p;
    char procedure[30][500];
} recipe;

int main(int argc, char *argv[])
{
    FILE* fbr;
    FILE* temp;
    char *ricetta_name = "recipe.bin";
    char *temp_name = "temp.bin";
    int found = 0;
    char name_t[40];

    // Use command line arguments if possible
    if (argc == 2)
    {
        ricetta_name = argv[1];
    }

    if((fbr = fopen(ricetta_name, "rb")) == NULL)
    {
       printf("Couldn't open the file %s.\n", ricetta_name);
       exit(1);
    }
    if((temp = fopen(temp_name, "wb")) == NULL)
    {
       printf("Couldn't open the file %s.\n", temp_name);
       exit(1);
    }

    printf("Write the name of the recipe you want to delete:\n");
    fgets(name_t, sizeof(name_t), stdin);

    // Remove '\n'
    if (name_t[strlen(name_t) - 1] == '\n')
        name_t[strlen(name_t) - 1] = 0;

    while(fread(&recipe,sizeof(recipe), 1, fbr))
    {  
        // Use standard strcasecmp()
        if(strcasecmp(name_t, recipe.name) == 0)
        {
            found = 1;
            printf("Match found. Recipe deleted.\n");
        }
        else
        {
            fwrite(&recipe, sizeof(recipe), 1, temp);
        }
    }

    if (!found)
    {
        printf("No match.\n");
    }

    fclose(fbr);
    fclose(temp);
    remove(ricetta_name);
    rename(temp_name,ricetta_name);
    return 0;
}

请格式化您的代码:在逗号(',')后添加空格('')。并尽可能使用标准功能。