Ваш код содержит несколько ошибок.
Давайте начнем с "неблокирующих" ошибок. Те, которые, даже если они могут быть действительно критическими и должны быть исправлены, не являются реальной причиной того, что вы испытываете sh.
- Грипп sh стандартного ввода,
fflush(stdin);
- это то, что не определено стандартом, поэтому его использование приводит к неопределенному поведению : в некоторых средах это может работать, в других - не может работать и может быть средой (худшей), в которой кажется работать, но на самом деле это вредно. Рекомендуется избегать этого. - Функция
gets()
опасна, поскольку она не обеспечивает какого-либо контроля над размером строки, вставленной пользователем, и ее использования следует избегать .
Проблемы в функции void addBook()
Вы пытаетесь увеличить доступное пространство, используя realloc
:
void * reallo c (void * ptr, size_t size);
Требуется исходный указатель и новый размер. Но вы передаете library.books_count
это просто количество книг. Это означает, что если в библиотеке было 4 книги, вы пытаетесь выделить 5 байт * только 1038 *.
Вместо этого вам нужно выделить library.books_count * sizeof(Sbook)
байт.
Кроме того, он возвращает новый указатель. Вам нужно присвоить его указателю книги:
library.bookp = realloc(library.bookp, library.books_count * sizeof(Sbook));
В
main()
вы инициализируете переменную
i
, но никогда не обновляете ее, поскольку храните номера книг непосредственно в
library.books_count
.
Затем передаете ее addexistingBooks()
, и это избыточно, потому что вы можете использовать library.books_count
для l oop, как вы это делаете. Вы можете использовать его как переменную l oop, но вам не нужно иметь этот параметр. Просто
void addexistingBooks(Slib library, )
{
int i; /* If your C version is C99 or later, you can declare it in the loop itself */
for(i=0;i<library.books_count;i++)
{
/* Omissis */
}
}
Наконец вы передаете его в addBook()
, и он не только избыточен (так как вы можете просто сохранить новую книгу по индексу library.books_count-1
, но он активно вреден, потому что вы всегда обновляете индекс 0 (потому что значение параметра i
равно 0).
Хотя можно
передавать структуры в функции в качестве значений , это не рекомендуется. Первая причина заключается в том, что вы будете перегружать стек процесса (вся структура будет размещена в области стека, которая довольно велика в приложениях P C, но довольно ограничена во встроенных системах). Вторая причина вызовет функциональные проблемы.
Фактически, параметры, передаваемые по значению, являются копиями переменных, переданных в функцию. Это означает, что любое изменение, внесенное в них, не будет отражено в исходных структурах. В вашем случае обновление указателя library.bookp
будет недоступно за пределами функции, в результате чего (1) исходная структура будет указывать на недопустимый адрес в памяти (становится висячий указатель ), (2) утечка вновь выделенной памяти, из-за которой никто не сможет free()
.
передавать структуры по адресу, вместо этого используя указатели на структуры . Функция addBook()
с учетом удаления параметра i
будет выглядеть следующим образом:
void addBook(Slib *library)
{
int i = library->books_count;
(library->books_count)++;
library->bookp = realloc(library->bookp, library->books_count * sizeof(Sbook));
/* and so on... the value of 'i' is now library->books_count-1 */
}
/* Call from main */
int main()
{
Slib library;
/* Omissis */
menu(Choice);
if(strcmp(Choice,"add")==0)
{
addBook(&library, i);
}
free(library.bookp);
return 0;
}