C编程数据输入错误

C编程数据输入错误,c,for-loop,struct,fgets,gets,C,For Loop,Struct,Fgets,Gets,我写这篇文章是为了获取学生信息(过去三个月的全名、id和gpa,所以我使用了结构和for循环来插入信息,但是,在第一次执行for循环之后(这意味着在学生2)我的第一个和第二个输入一起显示在屏幕上。我怎样才能以一种简单易懂的方式防止这种情况发生?(附言:我已经尝试将getchar()放在for循环的末尾,但它起了作用;我不应该使用它,因为我们在课堂上没有学习) c程序中发生错误的部分: #include <stdio.h> struct Student { char name[

我写这篇文章是为了获取学生信息(过去三个月的全名、id和gpa,所以我使用了结构和for循环来插入信息,但是,在第一次执行for循环之后(这意味着在学生2)我的第一个和第二个输入一起显示在屏幕上。我怎样才能以一种简单易懂的方式防止这种情况发生?(附言:我已经尝试将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;
}
#包括
结构学生{
字符名[30];
int-id;
浮动gpa[3];
};
浮动平均GPA(结构学生[]);
int main()
{
int i;
浮动平均;
struct Student studentlist[10];
i=0;

对于(i;i尝试在最后一次
scanf
之后吃换行符:

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

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

尝试在最后一次
scanf
之后使用换行符:

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

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

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

scanf(" %[^\n]",studentlist[i].name);
格式说明符中的第一个空格很重要。它从以前的输入中否定换行符。顺便说一下,格式指示读取,直到遇到换行符(\n)

[编辑:根据要求添加解释]

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

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

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

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

您将从web上获得有关这些说明符的更多信息。为方便起见,这里有一个链接:


开头的空格实际上“消耗”了先前输入的任何空白。您可以在此处参考答案以获得详细解释:

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

scanf(" %[^\n]",studentlist[i].name);
格式说明符中的第一个空格很重要。它从以前的输入中否定换行符。顺便说一下,格式指示读取,直到遇到换行符(\n)

[编辑:根据要求添加解释]

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

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

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

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

您将从web上获得有关这些说明符的更多信息。为方便起见,这里有一个链接:


开头的空格实际上“消耗”了以前输入时留下的任何空白。有关详细说明,您可以参考此处的答案:

,但您必须使用
getchar()
放弃上一次
scanf(“%f”)后仍在输入缓冲区中的换行符
,它根据给定的格式转换浮点,并将所有其他字符保留在缓冲区中

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

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


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

但您必须使用
getchar()
放弃上一次
scanf(“%f”)后仍在输入缓冲区中的换行符
,它根据给定的格式转换浮点,并将所有其他字符保留在缓冲区中

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

编辑说明:每当您在键盘上键入字符时,字符都会进入输入缓冲区,等待应用程序处理。getchar()只“消耗”此缓冲区中的一个字符(返回它),如果缓冲区为空,则等待有效字符。scanf(“%f”)只“消耗”字符,从而导致浮点。因此,当您键入“5.12”时,scanf读取并从缓冲区“5.12”中删除。因此,下一个fgets()已在缓冲区中找到一个换行符并立即返回;这就是