Почему выводит непонятные символы и смайлик?
Есть простая датабаза с играми. Я туда добавляю игры с помощью
if(games_stored == 100){
printf("Capacity has been reached!\n");
return;
}
char input[50];
int int_input = 0;
game_t * game = (game_t *) malloc( sizeof( game_t ) );
printf("\nPlease enter the game title ");
fgets(input, 50, stdin);
strcpy(game->title, input);
printf("\nPlease enter the game publisher ");
fgets(input, 50, stdin);
strcpy(game->publisher, input);
printf("Game has been stored on slot %d\n", store_game(game));
}
Я эти игры могу по слотам просматривать с помощью
int number;
printf("\n Enter the slot number\n");
scanf("%d", &number);
if(number > games_stored){
printf("\nThis game does not exist\n");
return;
}
printf("\nThe game in slot %d is %s by %s\n",
number,
games[number - 1]->title,
games[number - 1]->publisher
);
}
И я могу эти игры удалять из слотов с помощью
int number;
printf("\nEnter the slot number you want to delete\n");
scanf(" %d", &number);
free(games[number - 1]);
if(number > games_stored){
printf("\nThis game does not exist\n");
return;
}
printf("The game in slot %d has been deleted succesfully\n");
games_stored--;
}
НО Если удалять игры, начиная с последнего занятого слота (то есть удалять 3, потом 2, потом 1), То при выборе 2(Find game) названия отображаются нормально.
Однако если 3 слота заняты, а я удалю, например 1, то при попытке просмотреть этот слот выдаёт какие-то непонятные символы и смайлик???
Пример: "The game in slot 1 is P§LЄC☻ by Activision"
Полный код: https://pastebin.com/MNqN7z8G
Ответы (1 шт):
Ну ведь вы освободили память, на которую ссылался указатель. Обращаться после этого к ней - ошибка. Хорошо, что ещё смайлики отображаются, могла вообще программа рухнуть.
При выполнении free() вы освобождаете память, которую ранее выделяли. А указатель на этот кусок памяти как хранился в массиве, так и продолжает храниться и указывает в память, где ваших данных уже нету.
При этом, в функции удаления вы уменьшаете счетчик сохраненных игр games_stored--; и таким образом теряете игры, сохраненные в конце. Т.е. у вас 3 игры, вы удалили игру под индексом 0, счетчик уменьшился до 2. Если вы попытаетесь вывести данные об игре 3 (под индексом 2), вам выведет что такая игра не существует, хотя она есть.
if(number > games_stored)
{
printf("\nThis game does not exist\n");
return;
}
Ещё ошибка - вы сначала освобождаете память, а только потом проверяете, что введенный номер больше количества сохраненных игр.
free(games[number - 1]); // сначала освободили память
if(number > games_stored){ // а потом проверили - надо ли это делать
printf("\nThis game does not exist\n");
return;
}
Когда вы удалили последнюю в массиве игру, то больше вы к ней не обращаетесь , т.к. у вас стоят проверки - поэтому всё работает.
if(number > games_stored){}
Если вам не важно соблюдение порядка игр в списке, то можно поступить хитро - меняете между собой указатели с введенным индексом и последним и удаляете последний.
if(number < games_stored)
swap( games[number - 1], games[games_stored - 1]);
free(games[games_stored - 1]);
Если очередность важна, то используйте для хранения указателей вместо массива список - удаление элемента из середины не нарушает очередность.
Или смещайте (копируйте) все указатели в массиве после удаленного на 1.