繁体   English   中英

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

[英]Why does my program keep printing garbage values?

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

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

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

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

您使用未初始化的数据, 主要是:

  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);代替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"); 并且,最好是把其他换行之后的所有而不是之前刷新输出线,因此也改变printf("Index #[]\\tTime\\tDescription"); 通过puts("Index #[]\\tTime\\tDescription");

MAX不是一个很好的名称,因为它更像是一个SUP,或者只是将其重命名为SIZE

主要情况下,您不使用eventListSize


AddEventAtIndex中

--i必须 i = InputRange(1, 5); 或者只是i = InputRange(1, 5) - 1; 否则,当我的值为5时list[i]不在列表中,因此您使用未定义的行为写出列表

所以最后没有用的参数,将其删除。

main也不使用return索引,您可以使用它来分配i ,之后不使用i的值。 AddEventAtIndex不需要返回值。


InputRange中

您无需检查scanf的结果,因此如果输入了无效的整数,并且未清除输入,则所有下一个scanf都无法获得数字,因此timenumber的值是不确定的

同样,如果该值不在范围内,则只需调用InputRange(min, max); 而不返回其值,因此您最终将返回无效值,将所有内容都放入for(;;)例如,仅在值正确时才返回。

您在InputEvent中使用fgets ,将其与scanf混合以读取数字是问题的根源,请先使用fgets替换scanf ,再在读取行中使用sscanf


InputEvent中

当你做fgetc(stdin); 您可能希望绕过换行符,但是如果用户在InputRange中的数字之后输入字符(假设输入了数字),则fgets将读取其中的第一个字符,而fgets将无法获得预期的描述。 解决的办法是在InputRange要做然后fgets 的sscanf正如我上面让你删除龟etc


考虑到我的评论的建议:

#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中必须删除它

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM