Почему моя программа продолжает печатать значения мусора?
Вы используете неинициализированные данные, в main у вас есть:
Event e;
...
i = AddEventAtIndex(EventList, e, i);
, где e не инициализируется, но используется в AddEventAtIndex :
int AddEventAtIndex(Event list[], Event e, int i)
{
...
list[i].hour = e.hour;
list[i].minute = e.minute;
strcpy(list[i].description, e.description);
в поведении strcpy с неинициализированным значением не определено и может иметь драматические последствия.
Возможно, вызов InputEvent( EventList );
должен быть заменен на InputEvent(&e);
In
for ( int j = 1 ; j < 6 ; j++)
{
printf("\n[%d]\n\t%d:%d \t %s", j, EventList[j].hour,
EventList[j].minute, EventList[j].description);
}
Вы получаете доступ из EventList , когда j равно 5 и 6, сделайте, например:
for ( int j = 0 ; j < MAX ; j++)
{
printf("[%d]\t%d:%d \t %s\n", j+1, EventList[j].hour,
EventList[j].minute, EventList[j].description);
}
Но вы также пишете записи, никогда не устанавливая печатные значения мусора«Более того, факт печати строки без инициализации имеет неопределенный эффект.Способ разделения записей, установленных и не установленных, состоит в том, чтобы инициализировать все часы на 24 и проверить это значение в цикле, чтобы записать или нет запись.
Я также изменил формат, потому что символ новой строки после индексанесовместимо с printf("Index #[]\tTime\tDescription");
, и лучше поставить другую новую строку после все вместо до , чтобы очистить строку вывода, поэтому также измените printf("Index #[]\tTime\tDescription");
на puts("Index #[]\tTime\tDescription");
MAX не очень хорошее имя, потому что это больше SUP, или просто переименуйте его по РАЗМЕРУ
В main вы не используете eventListSize
In AddEventAtIndex
--i
должно быть сделано после i = InputRange(1, 5);
или просто сделать i = InputRange(1, 5) - 1;
иначе, когда i значений 5 list[i]
выходит за пределы списка , поэтому вы записываете из списка с неопределенным поведением.
Итак, наконецпараметр i бесполезен, удалите его.
Индекс возврата также не используется в main , вы используете его для присвоения i и не использовать значение i после. AddEventAtIndex не нужно возвращать значение.
In InputRange
Вы не проверяете результат scanf поэтому значение номер_иммера не определено, если было введено недопустимое целое число и если вы не удаляете ввод, поэтому все следующие scanf для получения числа не будут успешными
Кроме того, если значение не находится в диапазоне, вы просто вызываете InputRange(min, max);
, не возвращая его значение, поэтому, в конце концов, вы возвращаете недопустимое значение, поместите все в for(;;)
, например, для возврата только тогда, когда значение верное.
Вы используете fgets в InputEvent , чтобы смешать его с scanf , чтобы прочитать число - источник проблемы, замените scanf с помощью fgets , затем sscanf в строке чтения
In InputEvent
Когдавы делаете fgetc(stdin);
вы, вероятно, надеетесь обойти новую строку, но если пользователь вводит символы после числа в InputRange (предположим, что число было введено) fgets прочитает первый из них, а fgets не получит ожидаемое описание.Решение состоит в том, чтобы сделать fgets затем sscanf в InputRange , как я уже говорил выше, что позволит вам удалить fgetc
Предложение с учетом моих замечаний:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 5
struct event //data type called event which holds time and description for events
{
int hour; //holds the hour digit between 0-23
int minute; //holds the minute digit between 0-59
char description[41]; //holds the description for the reason of the alarm
};
typedef struct event Event; //allows coder to only have to use "Event" instead of "struct event"
int InputRange(int min, int max);
Event* InputEvent(Event *newEvent);
void AddEventAtIndex(Event list[], Event e);
//int InsertionSortEvent(Event list[], int *p_size, Event e);
//void DisplayEvent(Event e);
//void DisplayEventList(Event list[], int size);
//int DeleteEvent(Event list[], int i, int *p_size);
int main (void)
{
Event EventList[MAX];
Event e;
int choice;
/* mark uset entries */
for (int i = 0; i != MAX; ++i)
EventList[i].hour = 24;
do
{
printf("__= Scheduler v1.0 =__\n");
printf("1. Schedule an event.\n");
printf("2. Delete an event.\n");
printf("3. Display schedule.\n");
printf("4. Save schedule.\n");
printf("5. Load schedule.\n");
printf("6. Exit\n");
switch(choice = InputRange(1, 6))
{
case 1:
InputEvent( &e );
AddEventAtIndex(EventList, e);
break;
/*case 2: pHead = deleteStudent(pHead);
break;
case 3: printf("Press 1 to search by ID or 2 to search by name: \n");
scanf("%d", &search);
if (search == 1){
searchStudentID(pHead);
}
else if (search == 2){
searchStudentlName(pHead);
}
else{
printf("Invalid selection");
}
break;
case 4: displayStudentInfo(pHead);
break;
case 5: saveStudentInfo(pHead);
break;
case 6: end(pHead);
break;*/
default: printf("Exiting Program\n\n");
}
}
while ( choice != 6 );
puts("Index #[]\tTime\tDescription");
for ( int j = 0 ; j < MAX ; j++)
{
if (EventList[j].hour != 24)
printf("\t[%d]\t%d:%d \t %s\n", j+1, EventList[j].hour,
EventList[j].minute, EventList[j].description);
}
}
int InputRange(int min, int max)
{
char line[32];
int timenumber;
for (;;) {
printf("Please enter a number between %d - %d\n", min, max);
if (fgets(line, sizeof(line), stdin) == NULL)
/* EOF */
exit(-1);
if ((sscanf(line, "%d", &timenumber) == 1) &&
(timenumber >= min) &&
(timenumber <= max))
return timenumber;
printf("Invalid Entry\n");
}
}
Event* InputEvent(Event *newEvent)
{
if (newEvent != NULL) // quality assurance:
// make sure the pointer is valid
{
printf("Enter the event time:\n");
newEvent->hour = InputRange(0, 23);
newEvent->minute = InputRange(0, 59);
printf("Enter the event description:\n");
fgets(newEvent->description, sizeof(newEvent->description), stdin);
printf("\n");
}
return newEvent;
}
void AddEventAtIndex(Event list[], Event e)
{
printf("Where in the array would you like to store this event\n");
int i = InputRange(1, 5) - 1;
list[i].hour = e.hour;
list[i].minute = e.minute;
strcpy(list[i].description, e.description);
}
Компиляция и выполнение:
pi@raspberrypi:/tmp $ gcc -g -pedantic -Wextra -Wall c.c
pi@raspberrypi:/tmp $ ./a.out
__= Scheduler v1.0 =__
1. Schedule an event.
2. Delete an event.
3. Display schedule.
4. Save schedule.
5. Load schedule.
6. Exit
Please enter a number between 1 - 6
1
Enter the event time:
Please enter a number between 0 - 23
2
Please enter a number between 0 - 59
22
Enter the event description:
descr1
Where in the array would you like to store this event
Please enter a number between 1 - 5
1
__= Scheduler v1.0 =__
1. Schedule an event.
2. Delete an event.
3. Display schedule.
4. Save schedule.
5. Load schedule.
6. Exit
Please enter a number between 1 - 6
1
Enter the event time:
Please enter a number between 0 - 23
3
Please enter a number between 0 - 59
33
Enter the event description:
descr2
Where in the array would you like to store this event
Please enter a number between 1 - 5
4
__= Scheduler v1.0 =__
1. Schedule an event.
2. Delete an event.
3. Display schedule.
4. Save schedule.
5. Load schedule.
6. Exit
Please enter a number between 1 - 6
12
Invalid Entry
Please enter a number between 1 - 6
6
Exiting Program
Index #[] Time Description
[1] 2:22 descr1
[4] 3:33 descr2
обратите внимание на пустую строку в окончательном варианте, это потому, что новая строка является частьюописание, которое необходимо удалить присутствует в InputEvent