Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.54/13: Рейтинг темы: голосов - 13, средняя оценка - 4.54
187 / 180 / 25
Регистрация: 27.01.2012
Сообщений: 1,335
1

Удалить записанный экземпляр класса из двоичного файла

24.10.2012, 07:18. Показов 2511. Ответов 34
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Задача - удалить записанный экземпляр класса из дв. файла.
(В моём решении, удаленный экземпляр просто затирается последним)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
for (UINT i=0; i<patientsCount; ++i)
    {
        //fseek(patientsDatabase, (sizeof(patientsCount)+i*Size()), SEEK_SET); // X-ACTION
        ReadFile(patientsDatabase); //считываю экземпляр класса из дв. файла. Это метод\
Всё происходит в this
        if (_id == idRequired) // Требуемый Id для удаления
        {
            //DeleteCard(databases);
            if (patientsRequiredCount == 0)
                printf(Rus("-\nУдаленные записи\n"));
            printf(Rus("\nЗапись #%u\n"), i+1);
            //Print(); 
            PrintIdFile(patientsIdDatabase); // записываю this в дв. файл
            if (i < (patientsCount-1))
            {
                fseek(patientsDatabase, (sizeof(patientsCount)+(patientsCount-1)*Size()), SEEK_SET); // перехожу к последней записи дв. файла (Size() - размер структуры. Считает корректно)
                ReadFile(patientsDatabase); // считываю this
                fseek(patientsDatabase, (sizeof(patientsCount)+i*Size()), SEEK_SET); // перехожу к удаляемой записи
                PrintFile(patientsDatabase); // перезаписываю её
            }
            ++patientsRequiredCount;
            --patientsCount; // уменьшаю счетчик кол-ва записей
        }
    }
Проблема в том, что она не работает, если оставить всё так, как есть. Если разкомментировать строчку с fseek X-MOMENT, то всё начнет работать. Причем сам fseek никуда не двигает каретку в дв. файле. До X-MOMENT каретка стоит на 104 байте, после момента так же на 104 байте, но при этом следующий за ней ReadFile считывает все корректно.
Отчего такая феерическая ошибка? Может ли быть так, что, когда я сделал fseek на последнюю запись и считал её (ушел в EOF), то как-то нарушил всю суть работы? Хотя PrintFile после возврата каретки на текущую запись всё же отработал D:

Добавлено через 6 минут
Вместо X-ACTION можно вставить и такое. Тоже поможет :
C++
1
2
3
UINT id;
        fread(&id, sizeof(id), 1, patientsDatabase);
        fseek(patientsDatabase, -long(sizeof(id)), SEEK_CUR);
Ещё помогает передача параметра в ReadFile в виде FILE*& (с ссылкой)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.10.2012, 07:18
Ответы с готовыми решениями:

Можно ли считывать поля класса из двоичного файла одним fread
Можно ли считывать поля класса из двоичного файла одним fread? fread(this, sizeof(*this), 1,...

Создать экземпляр одного класса в Main, и передать его в экземпляр другого класса
Добрый день. Подскажите пожалуйста. есть несколько классов-файлов в одном пакете. class one...

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

Сборщик мусора (как удалить экземпляр класса)
В классе Main при клике на спрайт создаётся экземпляр класса Window: var window:Window; ......

34
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
24.10.2012, 14:56 2
Цитата Сообщение от nexen Посмотреть сообщение
Может ли быть так, что, когда я сделал fseek на последнюю запись и считал её (ушел в EOF), то как-то нарушил всю суть работы?
Код не смотрел, говорю на вскидку. Если поток дошёл до EOF, то потом, чтобы fseek работал, нужно сбросить флаги (по крайней мере, так с потоками в С++)
1
187 / 180 / 25
Регистрация: 27.01.2012
Сообщений: 1,335
24.10.2012, 15:44  [ТС] 3
alsav22, что значит "сбросить флаги"? И почему тогда работает даже после EOF при том хаке, что я написал?

Добавлено через 21 минуту
Цитата Сообщение от alsav22 Посмотреть сообщение
(по крайней мере, так с потоками в С++)
и что это значит?
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
24.10.2012, 16:03 4
Цитата Сообщение от nexen Посмотреть сообщение
что значит "сбросить флаги"? И почему тогда работает даже после EOF при том хаке, что я написал?
Это предположение, не более того. Код не смотрел.

Цитата Сообщение от nexen Посмотреть сообщение
и что это значит?
C++
1
2
fstream f("file.txt");
f.clear(); // сброс флагов потока
1
187 / 180 / 25
Регистрация: 27.01.2012
Сообщений: 1,335
29.10.2012, 14:37  [ТС] 5
alsav22, а, не, я через FILE* работаю.

Добавлено через 30 минут
Файл открыт r+b. Есть ли какие-либо особенности при работе с файлом, который открыт одновременно для чтения и записи, когда я в него записываю и читаю?

Добавлено через 5 часов 27 минут
Такое ощущение, что фокус в инкапсуляции какой-то.. Изменил всё на FILE*& и FILE**&, в итоге зайдя ещё глубже (из функции чтения передав в ещё одну функцию чтения свой файл), получил опять ту же проблему..

Будет ли какая-то разница, с каким из этих указателей работать?
C++
1
2
3
4
5
6
void f(FILE* f)
{
}
FILE *f1 = fopen("myfile.dat", "r+b");
FILE *f2 = f1, *f3 = f2, *f4 = f3;
f(f4);
Добавлено через 1 час 9 минут
Новый-старый фокус.
C++
1
ReadFile(file); // не работает
----------------------------
C++
1
2
fseek(file, ftell(file), SEEK_SET);
ReadFile(file); // работает
Добавлено через 11 часов 23 минуты
up-to-date

Добавлено через 7 часов 57 минут
Как сказал преподователь по ОС, это может быть из-за того, что, переходя в функцию, создается новый конекст файла, а когда я возвращаюсь из функции, забираю предыдущий контект (который теперь почему-то испорчен). fseek просто обновляет контект, поэтому и решает проблему.
Вопрос, как же тогда пользоваться контекстом?
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
29.10.2012, 16:16 6
По ссылке передай.
0
187 / 180 / 25
Регистрация: 27.01.2012
Сообщений: 1,335
29.10.2012, 16:24  [ТС] 7
alsav22, вроде бы как я писал, что везде поставил FILE*&..
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
29.10.2012, 16:36 8
Цитата Сообщение от nexen Посмотреть сообщение
переходя в функцию, создается новый конекст файла,
Что за контекст файла?

Добавлено через 2 минуты
Цитата Сообщение от nexen Посмотреть сообщение
Ещё помогает передача параметра в ReadFile в виде FILE*& (с ссылкой)
Тогда зачем этот вопрос?
Цитата Сообщение от nexen Посмотреть сообщение
Вопрос, как же тогда пользоваться контекстом?
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
29.10.2012, 16:39 9
Можете весь код выложить? А то не совсем понятно что у Вас происходит. По сути Вы достигаете eof при считывании последнего экземпляра. Устанавливается флаг EOF. fseek само собой его убирает. Подробней вот тут - http://www.cplusplus.com/refer... tdio/feof/

Нужная Вам часть:
Notice that stream's internal position indicator may point to the end-of-file for the next operation, but still, the end-of-file indicator may not be set until an operation attempts to read at that point.

This indicator is cleared by a call to clearerr, rewind, fseek, fsetpos or freopen. Although if the position indicator is not repositioned by such a call, the next i/o operation is likely to set the indicator again.
1
187 / 180 / 25
Регистрация: 27.01.2012
Сообщений: 1,335
29.10.2012, 17:04  [ТС] 10
Toshkarik, ага, а потом всё равно происходят ошибки, ведь после того, как я считал последнюю запись, я возвращаюсь не местоположение той, которую надо перезаписать и перезаписываю её, а затем, считывая следующую запись, я получаю ошибку.
Кода слишком много. Никто читать не будет >_<" Лишь напугает тех, кто хочет помочь. Описания проблемы будет достаточно. Если что-то непонятно, то так и скажите. Попытаюсь описать детальнее
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
29.10.2012, 17:09 11
nexen, потому что снова ставится EOF. Поставьте assert`ы feof() и посмотрите сами.
1
187 / 180 / 25
Регистрация: 27.01.2012
Сообщений: 1,335
29.10.2012, 17:50  [ТС] 12
Toshkarik, но почему? Ведь записываю я уже не в конец файла ><
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
29.10.2012, 17:57 13
Цитата Сообщение от nexen Посмотреть сообщение
возвращаюсь не местоположение той, которую надо перезаписать и перезаписываю её
При перезаписи до конца файла доходишь?

Цитата Сообщение от nexen Посмотреть сообщение
В моём решении, удаленный экземпляр просто затирается последним
Последний в файле? Может здесь до конца файла доходишь?

Добавлено через 55 секунд
Кода нет. Предлагаешь гадать?
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
29.10.2012, 17:58 14
Ведь написано:
Цитата Сообщение от Toshkarik Посмотреть сообщение
Although if the position indicator is not repositioned by such a call, the next i/o operation is likely to set the indicator again.
1
187 / 180 / 25
Регистрация: 27.01.2012
Сообщений: 1,335
29.10.2012, 18:09  [ТС] 15
Toshkarik, так в том то и дело, что он сбросился fseek'ом, как ты и сказал.
Покажу на примере. В файле :
4 1 2 3 4.
Первое число - кол-во записей, остальное - данные.
Считываю 4.
C++
1
for (int i=0; i<count; ++i)
Считываю 1.
Это требуемые к удалению данные. Перемещаюсь на начало 4 (предпоследняя запись, которую я смотрю не по SEEK_END, а по count).
Считываю 4ку. EOF
Перемещаюсь на начало 1. (EOF сбрасывается)
Записываю 4. (EOF не ставится, ибо не конец файла)
*В файле сейчас : 4 4 2 3 4*
Уменьшаю count на 1.
Считываю запись с текущего места (то есть должна быть 2ка, но тут происходит не пойми что и считывается как будто пара байт из 4ки и пара байт из 2ки и выходит 00 00 02 00 (если уже к примеру говорить).

Предположим, ошибки нет, то в конце перезаписываю count и получается файл :
3 4 2 3 4.
Так же, так как for идет до count, а я его уменьшил, то до EOF он уже никогда не дойдет
Запись 1 - удалена.
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
29.10.2012, 18:30 16
Покажите, как Вы вызываете fseek.
1
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
29.10.2012, 18:50 17
Объекты в файле как записаны? Непрерывная последовательность? Без разделителей?

Добавлено через 2 минуты
Цитата Сообщение от nexen Посмотреть сообщение
Считываю запись с текущего места (то есть должна быть 2ка,
Если строго по примеру, то будет не 2-ка, а пробел.
1
187 / 180 / 25
Регистрация: 27.01.2012
Сообщений: 1,335
29.10.2012, 18:52  [ТС] 18
Toshkarik, в первом сообщении темы. Строки 17-20.

alsav22, ну это я для наглядности. Пробелов нет. Записываемые классы представляют из себя строго фиксированную последовательность байт. vector/string или подобные нет. Только char*. Только с одинаковым new[STRING_SIZE].
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
29.10.2012, 18:59 19
Зачем цикл, если нужно переписать один объект?
0
187 / 180 / 25
Регистрация: 27.01.2012
Сообщений: 1,335
29.10.2012, 19:20  [ТС] 20
alsav22, планирую добавить удаление не только по id, так что оставил так.
0
29.10.2012, 19:20
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
29.10.2012, 19:20
Помогаю со студенческими работами здесь

Создать экземпляр метода класса или доступ к методу из экземпляра класса
Всем доброго времени суток!) Уже месяца как 2 не сишарпил и подзабыл...собственно задача такая:...

Как получить ссылку на текущий экземпляр класса внутри этого класса?
Как? Чтобы отрабатывал деструктор! и в нем можно было поиметь этот this ... Идея в том, что пишу...

Экземпляр класса как входные данные метода другого класса
Можно ли в качестве входных данных метода передать экземпляр метода другого класса? Если да, то как?

Создание указателя типа базового класса на экземпляр производного класса
Добрый день! Иногда видел коды, где создавался указатель типа базового класса на объект класса -...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru