由于某些原因,当我输入时间,描述和索引并单击“退出”以打印由值和字符串填充的数组时,我得到了一堆垃圾值,而不是我输入的值,我不确定我在做什么错误。有什么建议吗?
由于某些原因,当我输入时间,描述和索引并单击“退出”以打印由值和字符串填充的数组时,我得到了一堆垃圾值,而不是我输入的值,我不确定我在做什么错误。有什么建议吗?
#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);
int AddEventAtIndex(Event list[], Event e, int i);
//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 i=0;
int eventListSize = 0;
int choice;
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( EventList );
i = AddEventAtIndex(EventList, e, i);
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 );
printf("Index #[]\tTime\tDescription");
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);
}
}
int InputRange(int min, int max)
{
int timenumber;
printf("Please enter a number between %d - %d\n", min, max);
scanf("%d", &timenumber);
printf("\n");
if (timenumber < min || timenumber > max)
{
printf("Invalid Entry\n");
InputRange(min, max);
}
return timenumber;
}
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");
fgetc(stdin);
fgets(newEvent->description, 41, stdin);
printf("\n");
}
return newEvent;
}
int AddEventAtIndex(Event list[], Event e, int i)
{
--i;
printf("Where in the array would you like to store this event\n");
i = InputRange(1, 5);
list[i].hour = e.hour;
list[i].minute = e.minute;
strcpy(list[i].description, e.description);
return i;
}
答案 0 :(得分:2)
为什么我的程序继续打印垃圾值?
您使用未初始化的数据,在 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);
在
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); }
当j为5和6时,您从 EventList 中访问:例如:
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,或者只是将其重命名为SIZE
在 main 中,您不使用 eventListSize
在 AddEventAtIndex
--i
必须在之后 i = InputRange(1, 5);
完成,或者只做i = InputRange(1, 5) - 1;
,否则当 i 值5 list[i]
为不在 list 中,因此您以未定义的行为写出 list 。
所以最后参数 i 没用了,将其删除。
main 中也不使用返回索引,您可以使用它来分配 i ,之后不使用 i 的值。 AddEventAtIndex 不需要返回值。
在 InputRange
中您不检查 scanf 的结果,因此如果输入了无效的整数并且没有清除输入,则 timenumber 的值是不确定的下一个 scanf 获取数字将不会成功
如果该值不在该范围内,则仅调用InputRange(min, max);
而不会返回其值,因此最终返回无效值,例如,将所有值都放在for(;;)
中,仅当该值为正确。
您在 InputEvent 中使用 fgets ,将其与 scanf 混合以读取数字是问题的根源,请替换 scanf 使用 fgets ,然后在读取行上使用 sscanf
在 InputEvent
中当您执行fgetc(stdin);
时,您可能希望绕过换行符,但是如果用户在 InputRange 中的数字之后输入字符(假设输入了数字) fgets 将首先阅读其中的内容,而 fgets 不会获得预期的描述。解决方案是先在 InputRange 中执行 fgets 然后是 sscanf ,如上所述,您可以删除该 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
中删除它