【问题标题】:C Programming data input errorC 编程数据输入错误
【发布时间】:2012-09-07 11:05:34
【问题描述】:

我写这篇文章是为了获取学生信息(最后 3 个学期的全名、id 和 gpa,所以我使用结构和 for 循环来插入信息,但是,在第一次执行 for 循环之后(这意味着在学生 2 处)我的第一个和第二个输入一起显示在屏幕上。我怎样才能以一种简单易懂的方式防止这种情况发生?(P.S:我已经尝试将 getchar(); 放在 for 循环的末尾但是它确实有效;我不应该使用它,因为我们还没有在课堂上学习过)

我的错误发生的c程序部分:

 #include <stdio.h>

struct Student {
  char name[30];
  int id;
  float gpa[3];
};

float averageGPA ( struct Student [] );

int main()
{
  int i;
  float average;
  struct Student studentlist[10];
  i=0;

  for (i; i<10; i++)
  {
     printf("\nEnter the Student %d full name: ", i+1);
     fgets(studentlist[i].name, 30, stdin);
     printf("Enter the Student %d ID: ", i+1);
     scanf("\n %d", &studentlist[i].id);
     printf("Enter the Student %d GPA for the 1st trimester: ", i+1);
     scanf("%f", &studentlist[i].gpa[0]);
     printf("Enter the Student %d GPA for the 2nd trimester: ", i+1);
     scanf("%f", &studentlist[i].gpa[1]);
     printf("Enter the Student %d GPA for the 3rd trimester: ", i+1);
     scanf("%f", &studentlist[i].gpa[2]);
  }

  average = averageGPA(studentlist);

  printf("\n\nThe average GPA is %.2f", average); 

  return 0;
}

float averageGPA (struct Student studentlist[])
{
  int i;
  float total = 0.0, average = 0.0;
  for (i=0; i<10; i++)
  {
    total =  studentlist[i].gpa[0] + studentlist[i].gpa[1] + studentlist[i].gpa[2]; 
  }

  average = total / 30 ;
  return average;
}

电脑输出:

Enter the Student 1 full name: mm

Enter the Student 1 ID: 12

Enter the Student 1 GPA for the 1st trimester: 3

Enter the Student 1 GPA for the 2nd trimester: 4

Enter the Student 1 GPA for the 3rd trimester: 3

Enter the Student 2 full name: Enter the Student 2 ID: <<<<< Here is the problem!!

【问题讨论】:

  • 请以适当的缩进编辑您的帖子。它似乎在复制/粘贴过程中消失了。
  • 为什么不使用scanf 作为 name 字段,这与所有其他输入不同?

标签: c for-loop struct fgets gets


【解决方案1】:

尝试在最后一个 scanf 之后吃换行符:

scanf("%f ", &studentlist[i].gpa[2]);
         ^

这与您的getchar 解决方案非常相似。它实际上优于 getchar,因为它只丢弃空格。

【讨论】:

  • 我试过这个,但没有奏效。在我插入最后一个 gpa 并单击 enter 后,它一直给我空格(就像你在 msword 中按 enter 时一样)。
【解决方案2】:

但是您必须使用getchar() 丢弃在最后一个scanf("%f") 之后仍在输入缓冲区中的换行符,根据给定的格式转换一个浮点数并将所有其他字符留在缓冲区中。

如果您不能使用getchar(),请在循环结束时使用另一个fgets().. 当然getchar() 会更好

编辑解释:每当您在键盘上键入字符时,都会进入一个输入缓冲区,等待您的应用程序处理。 getchar() 只是从这个缓冲区“消耗”一个字符(返回它),如果缓冲区为空,则等待一个有效的字符。 scanf("%f") 仅“消耗”字符,导致浮点数。因此,当您键入“5.12”时,scanf 会从缓冲区“5.12”中读取并删除,留下“”。所以下一个 fgets() 已经在缓冲区中找到了换行符并立即返回;这就是为什么你应该使用 getchar(): 忽略它的返回值,你成功地从缓冲区中丢弃“”。最后请注意,如果缓冲区中只有 "",scanf("%f") 将丢弃它(因为它不能转换为浮点数)并等待另一个输入阻塞应用程序。

最后一点:输入流由您的操作系统默认策略缓冲,因为在您键入“”之前应用程序不会接收任何字符。

【讨论】:

  • 在格式字符串中带有空格的 scanf() (请参阅其他答案)会更好,因为它只丢弃空白字符,同时丢弃任意数量的空白字符(例如 CR+LF)而不仅仅是一个。
  • 我不知道 getchar() 到底是做什么的,但是在网上冲浪后,我看到很多人都在使用它,所以我尝试了一下,它确实有效。您能否向我提供有关 getchar() 函数的信息性解释,非常感谢您的帮助。保重
【解决方案3】:

按以下方式使用scanf读取学生姓名:

scanf(" %[^\n]",studentlist[i].name);

格式说明符中的第一个空格很重要。它否定先前输入的换行符。顺便说一下,格式指示读取直到遇到换行符 (\n)。

[编辑:应要求添加解释]

接受字符串的格式说明符是%s。但它只允许您输入非空白字符。另一种方法是在方括号内指定可接受的(或不可接受的,取决于场景)字符。

在方括号内,您可以指定单个字符、范围或这些字符的组合。要指定要排除的字符,请以插入符号 (^) 开头。

所以,%[a-z] 意味着 a 和 z 之间的任何字符(都包括在内)都将被接受

在您的情况下,我们需要接受除换行符以外的每个字符。所以我们想出了说明符%[^\n]

您将从网上获得有关这些说明符的更多信息。为方便起见,这里有一个链接:http://beej.us/guide/bgc/output/html/multipage/scanf.html

开头的空间实际上“消耗”了之前输入留下的任何前面的空白。详细解释可以参考这里的答案:scanf: "%[^\n]" skips the 2nd input but " %[^\n]" does not. why?

【讨论】:

  • 我试过了,效果很好,但我不知道你是怎么找到这个格式说明符的,稍微解释一下就好了。非常感谢您的帮助
  • 任何时候..:) 我看到仍然没有选择答案。如果其中一个答案被选为正确答案,将对每个人都有帮助。如果您的问题已经得到解答,那就是..
  • 有没有办法选择一个特定的答案,或者只是通过投票?
  • 每个旁边应该有一个勾号。单击您需要接受的答案旁边的那个。您可以查看常见问题解答以获取更多信息..哦..顺便说一下,欢迎使用 Stackoverflow :)
【解决方案4】:

我只想对 scanf() 说不。对所有输入字段使用 fgets() 并使用 atoi() 和 atof() 转换为数字。

【讨论】:

    猜你喜欢
    • 2011-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-12
    • 2012-02-22
    • 1970-01-01
    相关资源
    最近更新 更多