C - fseek() влияет на содержимое (структуру) файла при попытке обновить записи

Не уверен, что не так с fseek() в этой функции, поскольку я склонен полагать, что это является причиной проблем с неправильным выводом для моей программы.

   index = 0;
    present = 0;
    while(fread(&beverage, sizeof(struct beverages), 1, filepointer))
    {
        if(newFile == 0)
            break;

        printf("%s\n\n", beverage.bcode);
        getch();

        if(strcmp(_bev_name, beverage.bname) == 0)
        {
            printf("Inside if statement\n\n");
            getch();

            beverage.quantity = beverage.quantity + qty;
            beverage.qty_last_purchase = qty;


            priceOne = spent/qty;//Used to calculate the cost price for one beverage
            beverage.price = priceOne + (priceOne*0.10);//Calculation of sale price for beverage

            printf("%d\n\n", index);
            getch();

            fseek(filepointer,index*sizeof(struct beverages),SEEK_SET);
            fwrite(&beverage,sizeof(struct beverages),1,filepointer);

            present = 1;
            break;
        }
        else
        {
            present = 0;
            index = index + 1;
        }

    }

    if(present == 0)
    {
        //Stores new beverage name
        strcpy(beverage.bname, _bev_name);

        //Creation of beverage code using the first two letters of beverage name and random 3 digit number
        srand(time(NULL));
        int ran_num = rand()%(999 + 1 - 100) + 100;
        char str[3];

        itoa(ran_num, str,10);

        beverage.bcode[0] = beverage.bname[0];
        beverage.bcode[1] = beverage.bname[1];
        beverage.bcode[2] = str[0];
        beverage.bcode[3] = str[1];
        beverage.bcode[4] = str[2];
        beverage.bcode[5] = '\0';

        beverage.qty_last_purchase = qty;
        beverage.quantity = qty;
        priceOne = spent/qty;//Used to calculate the cost price for one beverage
        beverage.price = priceOne + (priceOne*0.10);//Calculation of sale price for beverage

        fwrite(&beverage, sizeof(struct beverages), 1, filepointer);

    }

Первая часть кода перебирает существующий файл, чтобы найти соответствующий код напитка, а затем обновить количество и цену напитка, но происходит то, что это влияет на другие структуры в файле.

Показывает, как отображаются напитки при их первом добавлении в файл

Показывает, как изменится список напитков после обновления записей

Следует отметить, что я решил обновить первый напиток на первом изображении, но, как вы можете видеть, это влияет на запись второго напитка.

РЕДАКТИРОВАТЬ: определение структуры напитков

struct beverages
{
    char bname[NAME_LIMIT];
    char bcode[MAX_SIZE];
    int quantity;
    int qty_last_purchase;
    float price;
} beverage;

person user3897992    schedule 31.03.2017    source источник
comment
Я не вижу, что не так с вашим кодом, но я вижу, что вы сочетаете последовательный доступ к файлу (полагаясь на то, что файл обновляет свою внутреннюю позицию в файле после чтения/записи) со случайным доступом к файлу (вызывая fseek().) Это может привести к большая проблема. Попробуйте вызывать fseek() каждый раз, чтобы перейти к определенному индексу записи перед чтением/записью записи.   -  person Mike Nakis    schedule 31.03.2017
comment
@MikeNakis, не могли бы вы привести мне пример, если это возможно ... Я немного новичок в C, поэтому я не совсем уверен, как говорить о том, что вы говорите.   -  person user3897992    schedule 31.03.2017


Ответы (1)


Хотя вы не показываете самую важную часть своего кода: определение struct beverages, я твердо убежден, что вы лаете не по тому дереву, и ваши проблемы не имеют никакого отношения к fseek().

Похоже, что struct beverages хранит не буквальные символы названия напитка в beverage.bname, а вместо этого указатель на них.

Таким образом, вы, скорее всего, сохраняете и извлекаете указатели вместо значений. Эти указатели указывают на бессмысленные данные после восстановления. Либо сохраните все свои данные внутри записей данных, либо ознакомьтесь с концепциями сериализации и десериализации.

person mfro    schedule 31.03.2017
comment
Сделано редактирование, показывающее определение структуры напитков. - person user3897992; 31.03.2017
comment
ок, хорошо выглядит. Следующее, на что нужно обратить внимание, — это использование itoa(). Это выглядит странно. - person mfro; 31.03.2017
comment
Должен ли я использовать sprintf вместо этого? - person user3897992; 31.03.2017
comment
либо так, либо исправить то, что есть. Вы ожидаете трехзначное число, которое будет использовать не менее четырех байтов при преобразовании в строку, но зарезервируете для него только три. - person mfro; 31.03.2017
comment
на самом деле ничего не меняет - person user3897992; 31.03.2017