C Project scanf()

2019-07-23 17:01发布

Here is my code, my statements is that when while loop starts to run show options and scan the selection at first iteration but in second iteration choice is not assigned again and previous selection is remembered. What is the problem ? (I am using VS2012)

while (!done){
    int choice;

    printf("\n------- STUDENT INFORMATION SYSTEM MAIN MENU --------\n");
    printf("1-Load students from the database\n");
    printf("2-Print existing students on the screen\n");
    printf("3-Add a new student\n");
    printf("4-Delete an existing student\n");
    printf("5-Find an existing student\n");
    printf("6-Quit\n");
    printf("====> Choice? ");
    scanf("%d", &choice);

    switch(choice){
      case 1:
        LoadStudentsFromDatabase();
        printf("Students loaded from database successfully\n");
        break;

      case 2:
        PrintExistingStudentsOnTheScreen();
        break;

      case 3:
        printf("\nFirstName: "); scanf("%s", s.firstName);

    printf("LastName: "); scanf("%s", s.lastName);
        printf("ID: "); scanf("%d", &s.id);
        printf("Gpa: "); scanf("%f", &s.gpa);
        printf("Department: "); scanf("%d", &s.department);

        AddStudent(&s);
        printf("1 student added\n");
        break;

      case 4:
        printf("\nID? "); scanf("%d", &id);
        if (DeleteStudent(id)){
          printf("Student deleted successfully\n");
        } else {
          printf("Failed to delete the student. Does not exist?\n");
        } /* end-else */
        break;

      case 5:
        printf("\nID? "); scanf("%d", &id);
        ps = FindStudent(id);
        if (ps == NULL){
          printf("Student not found\n");
        } else {
          char *depts[] = {"CS", "EE", "IE", "CE", "ME"};
          printf("+--------------------+--------------------+------+------+------+\n");
          printf("|    FirstName       |     LastName       |  ID  |  GPA | Dept |\n");
          printf("+--------------------+--------------------+------+------+------+\n");
          printf("|%20s|%20s|%6d|%6.2f|%6s|\n", ps->firstName, ps->lastName, ps->id, ps->gpa, depts[ps->department]);
          printf("+--------------------+--------------------+------+------+------+\n");
        } //end-else
        break;

      case 6:
        done = 1;
        break;

      default:
        printf("!!!!!!!!!! Invalid choice. Try again :-))\n");
        break;
    } /* end-switch */
  } /* end-while */

标签: c scanf
2条回答
女痞
2楼-- · 2019-07-23 17:39

Actually your code is behaving as expected.

The behaviour can be reproduced with the following input

FirstName: f
LastName: l
ID: 1
Gpa: 2
Department: d

Department expects an int as input, when you type in something else, d in this case, the scanf keeps looking for an int as you are looping, so the line scanf("%d", &choice); fails too to read an int and choice is not reassigned a new value, so the switch statement always sees the last valid value for choice. the loop pauses then at the next read attempt.

To solve your problem you need to validate the input and go to the next step only if the input you are expecting is valid. You can do this by checking the return value of scanf witch is the number of items successfully parsed according to the conversion patterns, in your case you want to read only one item.

Here is a basic way how you could validate an integer input

int read_integer(char* what)
{
    int i = 0;
    printf("%s: ", what);
    int r = scanf("%d", &i);
    while(r == 0) {
        while('\n' != getchar())
            // consume the rest of input until a LF comes (enter pressed)
            ;
        printf("Bad input for %s, try again (r=%d)\n", what, r);
        printf("%s: ", what);
        r = scanf("%d", &i);
    }
    return i;
}

and here how you could read Department

int department = read_integer("Department");

You could also write a similar function for float -> float read_float(char*){...}

查看更多
forever°为你锁心
3楼-- · 2019-07-23 17:41

What is probably happening is that when you call scanf for the second time around there is an error. Probably because a non digit input is waiting to be read on stdin. Maybe you didn't fully read all your input during the body of your code last time around? scanf tries to read a digit and only a digit because of your conversion format %d so if the next thing to be read is not a digit it fails it returns an error and leaves choice untouched. You do not check for this error so assume choice contains a newly entered value when in fact it just contains whatever it contained before scanf was called. scanf can also fail for more error like reasons as well but I suspect thats not the case here.

My suggestion would be:

a) check the return value of scanf. It should return 1 in your case. If it does not there has been an error. You can either bail out or just present the menu again.

b) Have a look at fpurge/fflush. I'm not sure what will be available to you using VC++ but Google will find you equivalents. Those functions can be used to discard pending input before calling scanf.

HTH

查看更多
登录 后发表回答