为什么我的程序会继续打印垃圾值?

时间:2019-03-26 21:35:58

标签: c

由于某些原因,当我输入时间,描述和索引并单击“退出”以打印由值和字符串填充的数组时,我得到了一堆垃圾值,而不是我输入的值,我不确定我在做什么错误。有什么建议吗?

由于某些原因,当我输入时间,描述和索引并单击“退出”以打印由值和字符串填充的数组时,我得到了一堆垃圾值,而不是我输入的值,我不确定我在做什么错误。有什么建议吗?

#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;
}

1 个答案:

答案 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

中删除它