• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

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

    Запись на курс до 25 апреля. Получить промодоступ ...

Запись/чтение структруры в бинарный (двоичный) файл

  • Автор темы BattleMage
  • Дата начала
B

BattleMage

if( !ferror( db ) )
{
...
} не помогло...

Но в прочем неважно. Методом шаманных преобразований все получилось.
Так что там насчет красивого оформления программ?
 
P

Pasha

Для: BattleMage
Без шаманских преобразований:
Код:
	while (fread(ptr,sizeof(kniga),1,db)) {...
 
E

European

Для: Pasha
MSDN:
Use the feof or ferror function to distinguish a read error from an end-of-file condition.
Для: BattleMage
Ты не ответил на мой предыдущий вопрос. Похоже ты просто добавляешь лишнюю строку после чтения последней записи
 
E

European

Все сказанное ниже ИМХО, поэтому спорить по этому поводу не буду.
1 - раз все заработало, выкинь ты нафиг эти malloc-и
2 - char god_izdaniya[10]; - улыбнуло! Ты год 10-символами записываешь? Тогда уж лучше char god_izdaniya[4] или вообще int.
3 - как уже говорил Pasha используй безопасные функции копирования типа strncpy.
4 - не объявляй глобальные переменный типа FILE *db и kniga *ptr, если ты их используешь только локально.
5 - ну и код форматируй отступами, а то тяжело читать. И тегами кода пользуйся на форуме
 
B

BattleMage

1) "2 - char god_izdaniya[10]; - улыбнуло! Ты год 10-символами записываешь? Тогда уж лучше char god_izdaniya[4] или вообще int."
ну например 1536 от Рождества Христова :) кстати больше чем 10. Надо 25 поставить :D
или 45 до н.э.

2) FILE *db и kniga *ptr кто тебе сказал что я использую их только локально?.. просто я не весь код присылал

5) я так делаю. когда прогу пишу. но когда текст копирую, тут он отступы убирает...

3) а что за функция strncpy?
 
E

European

1) Ну если тебе нужно так записывать год, то ладно...
2) Даже с учетом того, что ты привел не весь код, это плохой тон и потенциальный источник ошибок.
5) Странно :)
3) Позволяет копировать строку символов аналогично strcpy с указанием 3-м параметром длины строки
 
E

European

Для: Pasha
Считаешь это убедительным доводом?
Из MSDN:
fread returns the number of full items actually read, which may be less than count if an error occurs or if the end of the file is encountered before reaching count.
Use the feof or ferror function to distinguish a read error from an end-of-file condition.
If size or count is 0, fread returns 0 and the buffer contents are unchanged.
Ты со своим подходом считаешь 2 байта из потока и будешь свято верить, что все ОК, а юзер будет материть разработчика. Если хочешь проверять успешность чтения через fread, то стоит писать что-то вроде
Код:
while ( fread(ptr,sizeof(kniga),1,db) == sizeof(kniga) ) {...
, и то я считаю что это не есть хорошо

P.S. Получилось 666 сообщение :)
 
P

Pasha

Для: European
Читай внимательно цитату: fread returns the number of full items actually read. Не байт, а полных айтемов, размер которых в байтах ты указываешь 3-м параметром!
 
E

European

А, чёрт, ты прав :) Но сути это не меняет
 
B

BattleMage

Ну так вот. У меня опять не выходит... :(
Ещё надо бы редактировать запись. Вот пользователь тыкнул на какую-то строку стринггрида, и надо её отредактировать (изменить название, автора ...)

FILE *db;
rewind(db);
ptr=(kniga*)malloc(sizeof(kniga));
while (!feof(db))
while (fread(ptr,sizeof(kniga),1,db))
if (ptr->nomer==a)
{
strcpy(ptr->nazvanie,Form3->Edit1->Text.c_str());
strcpy(ptr->avtor,Form3->Edit2->Text.c_str());
strcpy(ptr->zhanr,Form3->Edit3->Text.c_str());
strcpy(ptr->izdatelstvo,Form3->Edit4->Text.c_str());
strcpy(ptr->god_izdaniya,Form3->Edit5->Text.c_str());
Form1->StringGrid1->Cells[0][a]=IntToStr(ptr->nomer);
Form1->StringGrid1->Cells[1][a]=ptr->nazvanie;
Form1->StringGrid1->Cells[2][a]=ptr->avtor;
Form1->StringGrid1->Cells[3][a]=ptr->zhanr;
Form1->StringGrid1->Cells[4][a]=ptr->izdatelstvo;
Form1->StringGrid1->Cells[5][a]=ptr->god_izdaniya;
break;
}

a - номер строки которую выбрал пользователь для редактирования.
Из Form3->Edit1->Text.c_str() и т.д. записываются новые данные (вместо старых) - таким образом происходит редактирование

Вобщем происходит ошибка:
"Access violation at address 32665A01 in module 'CC3260MT.DLL'. Write of address F82686B0."

Что я на этот раз не так сделал?

Номер является уникальной характеристкой, если фамилия автора может совпадать, то номер - нет. если нашли... стоп... я же не записывал, его в файл (номер). может в этом ошибка?!
 
P

Pasha

Для: BattleMage
Ошибка ведь происходит на конкретной строчке. Найди эту строчку и попытайся понять что в ней не так.
 
B

BattleMage

Ты думаешь я не пробывал искать? Вроде все так. Прогуливаемся по файлу пока он не кончится. Если удалось считать и номер его совпал, то заменяем исходные значения на некоторые новые, введенные пользователем
 
B

BattleMage

Блин. Работает вроде. Но вот только изменяет ячейки стринггрида, а не сам файл. Уж как только не попробывал все режимы открытия файла. Думаю: почти все так же как и при добавлении... Но вот что-то не выходит...

[/code]
FILE *db=fopen("database.xxx","a+b");
rewind(db);
ptr=(kniga*)malloc(sizeof(kniga));
while (!feof(db))
while (fread(ptr,sizeof(kniga),1,db))
{
if (ptr->nomer==:(
{
strcpy(ptr->nazvanie,Form3->Edit1->Text.c_str());
strcpy(ptr->avtor,Form3->Edit2->Text.c_str());
strcpy(ptr->zhanr,Form3->Edit3->Text.c_str());
strcpy(ptr->izdatelstvo,Form3->Edit4->Text.c_str());
strcpy(ptr->god_izdaniya,Form3->Edit5->Text.c_str());
Form1->StringGrid1->Cells[0]=IntToStr(ptr->nomer);
Form1->StringGrid1->Cells[1]=ptr->nazvanie;
Form1->StringGrid1->Cells[2]=ptr->avtor;
Form1->StringGrid1->Cells[3]=ptr->zhanr;
Form1->StringGrid1->Cells[4]=ptr->izdatelstvo;
Form1->StringGrid1->Cells[5]=ptr->god_izdaniya;
fwrite(ptr,sizeof(kniga),1,db);
}
}
free(ptr);
fclose(db);
Код:
b - строка стринггрида выбранная для редактирования пользователем


мля... дурацие смайлы. Тут должно быть:
if ( ptr->nomer==b )
 
B

BattleMage

Кстати, указатель на элемент структуры не нужен? Ну если не нашли, то сразу переходим к другому - по-моему, довольно-таки правильно...

Только вот опять не работает:

FILE *db=fopen("database.xxx","r+b");
rewind(db);
ptr=(kniga*)malloc(sizeof(kniga));
while (!feof(db))
while (fread(ptr,sizeof(kniga),1,db))
{
if (ptr->nomer==b )
{
strcpy(ptr->nazvanie,Form3->Edit1->Text.c_str());
strcpy(ptr->avtor,Form3->Edit2->Text.c_str());
strcpy(ptr->zhanr,Form3->Edit3->Text.c_str());
strcpy(ptr->izdatelstvo,Form3->Edit4->Text.c_str());
strcpy(ptr->god_izdaniya,Form3->Edit5->Text.c_str());
Form1->StringGrid1->Cells[0]=IntToStr(ptr->nomer);
Form1->StringGrid1->Cells[1]=ptr->nazvanie;
Form1->StringGrid1->Cells[2]=ptr->avtor;
Form1->StringGrid1->Cells[3]=ptr->zhanr;
Form1->StringGrid1->Cells[4]=ptr->izdatelstvo;
Form1->StringGrid1->Cells[5]=ptr->god_izdaniya;
}
else ptr=ptr->sled;
fwrite(ptr,sizeof(ptr),1,db);
}
free(ptr);
fclose(db);
 
P

Pasha

Для: BattleMage
Тебе знакомо понятие "отладка"?
 
B

BattleMage

Ну вообще слышал :(
Трассировка и т.д.
Может я просто совсем неправильно делаю. Вообще как надо? Считать всю структуру и искать
while (!feof(db))
while (fread(ptr,sizeof(kniga),1,db))
if (ptr->nomer==b )
{
...
}
да?

и вот. самое главное. как записывать. все-все записать заново режим "wb", или как-то дописать пытаться?
 
B

BattleMage

Pasha, вот в обычном паскале под ДОС пошаговый запуск осуществляется кнопкой F7. Как это сделать в С++Builder-e? Он просматривает процедуры создания форм, а не нажатия на клавиши, которые собственно самые главные...
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!