Создать базу данных мониторов - C (СИ)
Формулировка задачи:
Имеется курсач - создать базу данных мониторов. Сейчас надо организовать бинарный файловый ввод/вывод структуры с помощью fread()/fwrite(). Память под записи выделяется динамически, записи объединены двусвязным списком.
Проблемы сейчас следующие:
1) не работает
while( !feof(fp) )
: (строка 79 ) - при открытии пустого файла пропускает в цикл; - при открытии файла с записями при достижении (?) конца файла опять пропускает в цикл; Не понимаю, где находится маркер потока ввода после открытия файла. При добавленииputc(fp)
начинает ловить EOF пустого файла, в записанном, естественно, съедает первый байт и на выводе получается каша. Пробовал сдвигать маркер вводаfseek()
на 1, 2 и 3 байта - всё-равно пропускает в цикл. Получается при открытии файла маркер потока ввода находиться за файлом (вроде равен нулю, а не первому байту, где стоит EOF) или как? 2) После считывания записей из файла убивает сортировки записей (пузырьком и вставками ) вsegmentation fault
. Код сортировок здесь не привожу, смысла нет. Просто подскажите в каком виде эта считанная из файла структура попадает в память: становятся ли бывшие строки строками, приводятся ли числа к своим типам. В той же сортировке пузырьком по полюsize[]
ошибку выбивает на первом же этапе сравнения строк по длине черезstrlen()
. Тут у меня никаких идей нет, разве что строки не закрыты '\0'? Код такой:#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct base
{
char name[30];
float power;
char size[11];
unsigned long long int color;
struct base * next, * prev;
};
struct base * load( FILE * , struct base * ); /* функция считывания из файла */
void close( FILE * , struct base * , struct base * , struct base * , const char * const ); /* функция записи в файла */
int main( int argc , char * argv[] )
{
unsigned short num;
struct base * first = NULL , * begin = NULL , * last = NULL;
FILE * fp = NULL;
/* обработка открытия файла */
if( argc != 2 )
{
fputs("\n################################################################\n"
"## Файл для сохранения БД отсутствует! ##\n"
"## После закрытия программы вся работа с БД будет утеряна! ##\n"
"## Для подключения файла введите первым ключом его имя. ##\n"
"################################################################\n" , stdout);
fputs("\nДля продолжения нажмите Enter...\n" , stdout);
getchar();
}
else if( argc == 2 && ( fp = fopen( argv[1] , "rb+") ) == NULL )
{
printf("Файл недоступен - %s\n", argv[1]);
exit(1);
}
else if( argc == 2 && fp != NULL )
{
fprintf(stdout , "Файл \"%s\" открыт для считывания...\n", argv[1]);
first = load( fp , first );
/* флаг начального указателя; если begin и first различны - переписать файл БД */
begin = first;
/* последный указатель на данные из файла */
for( last = first ; first != NULL && last->next != NULL ; last = last->next );
}
/* далее меню */
while( 1 )
{
system("clear");
fputs("Работа с базой данных мониторов.\n"
"\nВыберите нужный пункт:\n"
/* часть кода пропущена */
"9. Завершить работу с базой.\n" , stdout);
while( scanf("%hu", &num) != 1 || num == 0 || num > 9 )
{ puts("Неверный ввод!\nПовторите ввод:"); getchar(); }
system("clear");
switch(num)
{
/* часть кода пропущена */
case 9: close( fp , begin , first , last , argv[1] );
fputs("Работа завершена!\n" , stdout);
exit(0);
}
}
}
struct base * load( FILE * fp , struct base * first )
{
unsigned int num = 0;
struct base * current, * down = NULL;
while( !feof(fp) ) /* почему-то не работает? */
{
/* динамически выделяется память */
current = (struct base *) malloc( sizeof(struct base) );
if( current == NULL )
{
fputs("Ошибка инициализации памяти!\n" , stderr);
exit(2);
}
if( first == NULL )
first = current; /* флаг первой записи */
else if( down == NULL ) /* в этом входе в load() записи ещё не вводились! */
{
down = first;
while( down->next != NULL ) /* пробежда имеющихся записей при каждом входе в функцию */
{
down = down->next;
num++;
}
num++;
down->next = current;
}
else
down->next = current;
current->next = NULL;
current->prev = down;
down = current; /* в начале цикла создастся новый current */
/* начинает считывать из файла */
if( fread( current , sizeof(struct base) , 1 , fp ) != 1 )
{
if( feof(fp) )
break;
fprintf( stderr , "Запись #%u.\nОшибка считывания!\n" , num);
exit(3);
}
else
num++;
}
num ? fprintf(stdout , "Из файла считано %u записей.\n", num) : fputs("Файл пуст.\n" , stdout);
fputs("\nДля продолжения нажмите Enter...\n" , stdout);
getchar();
return first;
}
/* указ. на 1-ю запись из файла , текущий 1-ый указ. БД , указ. на последнюю запись из файла */
void close( FILE * fp , struct base * begin , struct base * current , struct base * last , const char * const argv )
{
unsigned int num;
if( fp != NULL )
{
/* если begin и first различны - переписать файл БД */
if( current != begin )
{
rewind(fp);
last = current;
}
else
last = last->next;
for( num = 1 ; last != NULL ; ++num , last = last->next )
if( fwrite( last , sizeof(struct base) , 1 , fp ) != 1 )
{
fprintf( stderr , "Запись #%u.\nОшибка записи!\n" , num );
exit(3);
}
if( fclose(fp) != 0 )
{
fprintf(stderr , "Невозможно сохранить файл - %s\n", argv);
exit(1);
}
}
while( current != NULL )
{
free(current);
current = current->next;
}
return;
}Решение задачи: «Создать базу данных мониторов»
textual
Листинг программы
if( feof(fp) )