Использование fseek() для обновления двоичного файла

Я искал и искал в Интернете помощь по эффективному использованию fseek(), но независимо от того, что я делаю, я все еще не получаю правильных результатов. В основном я читаю из файла животных, у которых есть параметр «возраст». Если возраст равен -1, то после добавления в этот двоичный файл я должен использовать fseek(), чтобы найти первую -1 в файле и перезаписать всю эту строку новой информацией, которую вводит пользователь. У меня есть массив, который проходит и находит все дыры в начале файла, и он работает правильно. Моя проблема в том, что он обновляет новое животное и помещает каждое в следующий пустой слот с возрастом -1, но когда я иду обновлять свой файл, все животные добавляются в конец, даже если их идентификаторы являются идентификаторами когда-то пустых слотов. Вот мой код:

void addingAnimal(FILE *file, struct animal ani, int * availableHoles) {
    int i;
    int offset = ((sizeof(int) + sizeof(ani)) * ani.id -1);
    if (availableHoles[0] != 0) {
        fseek(file, offset, SEEK_SET);
        ani.id = availableHoles[0];
        fwrite & ani, sizeof(ani), 1, file);
        for (i = 0; i < sizeof(availableHoles) -1; i++) {
            availableHoles[i] = avialablesHoles[i+1];
        }
}

В самом начале файла есть целое число, которое сообщает нам количество отверстий в файле, поэтому смещение удаляет это, поэтому, как только я его печатаю, он печатает все правильно. Затем я проверяю, есть ли дыры в созданном мной вспомогательном массиве, если они есть, то я хочу, чтобы идентификатор животного был этим идентификатором, и я пытаюсь найти строку с первым -1 возрастом, чтобы поместить туда обновленную информацию о моем животном. , а затем записать его в файл. В последнем цикле for я просто перемещаю доступные отверстия. Да, и что касается открытия файла, я использую r+b для чтения и записи. Заранее спасибо!


person user3376654    schedule 13.12.2015    source источник
comment
Как вы открыли файл? Какие аргументы вы передали fopen()? Похоже, что файл был открыт в режиме добавления.   -  person fuz    schedule 13.12.2015
comment
Я заявил в предпоследнем предложении, что использовал r+b, который, как я читал, является наиболее подходящим способом открытия при изменении файла так, как я намереваюсь.   -  person user3376654    schedule 13.12.2015
comment
Хорошо, не могли бы вы сделать минимально воспроизводимый пример?   -  person fuz    schedule 13.12.2015
comment
Должен ли ani.id -1 быть в скобках?   -  person Johnny Mopp    schedule 13.12.2015
comment
Извините, я не знаю, что это такое..   -  person user3376654    schedule 13.12.2015
comment
@user3376654 user3376654 Нажмите на ссылку, чтобы узнать.   -  person fuz    schedule 13.12.2015
comment
Возможно, я неправильно рассчитываю свое смещение.   -  person user3376654    schedule 13.12.2015
comment
этот последний цикл for() в опубликованном коде сместит данные к более ранней записи в массиве availableholes, но не сможет «очистить» последнюю запись, поэтому теперь будет 2 повторяющихся записи, затем 3 повторяющихся записи, только больше дублировать запись каждый раз, когда вызывается опубликованный код   -  person user3629249    schedule 14.12.2015
comment
Я подозреваю, что эта строка: int offset = ((sizeof(int) + sizeof(ani)) * ani.id -1); должна быть: int offset = ((sizeof(int) + sizeof(ani)) * (ani.id -1));   -  person user3629249    schedule 14.12.2015


Ответы (1)


Вы не можете использовать sizeof(availableHoles) для перебора массива. Вы находитесь в функции, которая получает availableHoles в качестве указателя, ее размер не имеет отношения к количеству отверстий.

Передайте количество элементов этого массива в качестве отдельного аргумента.

Использование потоков FILE в режиме чтения/записи сложно, вызываете ли вы fseek() систематически между доступом в режиме чтения и режиме записи?

Опубликуйте код вызова, одной функции addingAnimal недостаточно для исследования вашей проблемы.

person chqrlie    schedule 13.12.2015
comment
Я полагаю, вы имеете в виду мой цикл for в самом конце, то есть просто для обновления пустых дыр. Насколько я понимаю, эта часть работает правильно, это я ищу нужную строку файла, с которой у меня проблемы. - person user3376654; 13.12.2015
comment
@user3376654 user3376654 Нет, это работает неправильно. Если вы не верите в это, поместите оператор печати в цикл for. Вы должны обнаружить, что он не распечатывает количество раз, которое вы намеревались запустить цикл. Это может быть или не быть основной причиной вашей проблемы, но это, безусловно, неправильно и должно быть исправлено, чтобы исключить эту возможность. - person kaylum; 13.12.2015