2013-03-16 78 views
1

这里是我的代码,我的陈述是,while循环开始运行show选项并在第一次迭代时扫描选择,但在第二次迭代中,不会再次指定选择,并且会记住先前的选择。问题是什么 ? (我正在使用VS2012)C项目scanf()

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 */ 
+1

你真的应该验证scanf调用的返回值(事实上,在''',例如'if(scanf(“%d”,&choice)!= 1)/ * error * /;' – pmg 2013-03-16 09:53:45

+0

我无法重现您描述的行为。你能想出一个SSCCE(http://sscce.org/)吗? – NPE 2013-03-16 10:04:10

+2

[您的ideone代码(我的SSCCE)](http://ideone.com/mwzH4f)的行为如预期! – pmg 2013-03-16 10:23:07

回答

0

可能发生的情况是当您第二次调用scanf时出现错误。可能是因为一个非数字输入等待在stdin上读取。也许你上次在你的代码体内没有完全读取所有输入内容?由于您的转换格式012f,scanf会尝试读取一位数字和一位数字,因此如果要读取的下一个数据不是数字,则会失败,它会返回错误并保持choice不变。你不检查这个错误,所以假设choice包含一个新输入的值,实际上它只是包含scanf被调用之前包含的任何值。 scanf也可能会因为更多的错误而失败,但我怀疑这种情况并非如此。

我的建议是:

a)检查scanf的返回值。它应该返回1在你的情况。如果它不存在错误。您可以退出或再次出现菜单。

b)看看fpurge/fflush。我不确定使用VC++可以获得什么,但Google会发现您是等同的。这些函数可用于在调用scanf之前丢弃未决的输入。

HTH

0

实际上,您的代码的行为与预期相同。

行为可以用下面的输入转载

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

Department预计的int作为输入,当你在别的东西,d在这种情况下键入时,scanf不断寻找一个int因为你是循环,因此行scanf("%d", &choice);也无法读取int,并且choice未重新分配新值,因此switch语句始终会看到choice的最后一个有效值。该循环在下次读取尝试时暂停。

要解决您的问题,您需要验证输入并且只有在您期望的输入有效时才转到下一步。你可以通过检查scanf的返回值来做到这一点,女巫是根据转换模式成功解析的项目数量,在你的情况下,你只需要阅读one项目。

下面是一个基本方式,你如何能验证一个整数输入

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

,在这里你怎么能读Department

int department = read_integer("Department"); 

你也可以写一个类似的功能float - >float read_float(char*){...}