c - Gets/fgets 跳过 C 中的输入步骤
问题描述
我有一个练习,我需要创建一个程序来输入学生的所有信息作为学生报告,如下面的源代码。我有一个问题,我无法获得完整的流输入。它跳过成绩输入并跳转到另一个学生输入下一个学生的ID。我已经把getchar()
得到\n
,但它没有帮助。我的问题是开关的情况1,所以你只需要关心它,其他情况在我的问题中没有任何意义。
#include <stdio.h>
#include <string.h>
#define MAX 1000
typedef struct
{
char id[10];
char name[50];
float grade;
char assess;
}student;
char assess(int a)
{
if(a<4.00)
return 'F';
if(4.00<=a<6.00)
return 'D';
if(6.00<=a<7.00)
return 'C';
if(7.00<=a<8.50)
return 'B';
if(8.50<=a<10.00)
return 'A';
}
int main()
{
int choice;
int i=0, num=0;
int a=0, j=0;
student std[MAX], temp;
char search[50];
do
{
printf("Student Report\n");
printf("1.Input data\n2.Append data\n3.Sort data and print\n4.Search by names5.Quit\n");
printf("Your choice is: ");
scanf("%d", &choice);
switch(choice)
{
case 1:
{
do{
printf("How many students you want to add?\n");
scanf("%d", &num);
if(num<0 || num>50)
printf("Your number must be positive or smaller than or equal to 50!\n");
}while(num<0||num>50);
for(i=a; i<num; i++)
{
printf("Student's id No.%d:", i);
fgets(std[i].id, 10, stdin);
getchar();
printf("Student's name No.%d:", i);
fgets(std[i].name, 50, stdin);
getchar();
printf("Student's grade No.%d:", i);
scanf("%f", &std[i].grade);
std[i].assess=assess(std[i].grade);
}
a=num;
}
case 2:
{
do
{
printf("How many students you want to append?[0; %d]\n", MAX-num);
scanf("%d", &num);
}while(num<0||num>50-a);
for(i=a; i<num+a; i++)
{
printf("Student's id No.%d:", i);
fgets(std[i].id, MAX, stdin);
getchar();
printf("Student's name No.%d:", i);
fgets(std[i].name, MAX, stdin);
getchar();
printf("Student's grade No.%d:", i);
do
{
scanf("%f", &std[i].grade);
if(std[i].grade<0||std[i].grade>10)
printf("Please re-input grade, it must be between 0 and 10\n");
}while(std[i].grade<0||std[i].grade>10);
std[i].assess=assess(std[i].grade);
}
a=num+a;
}
case 3:
{
for(i=0; i<a; i++)
for(j=0; j<a; j++)
{
if(std[i].grade<std[j].grade)
{
temp=std[i];
std[i]=std[j];
std[j]=temp;
}
}
printf("ID\tName\t\t\tGrade\t\tAssessment\n");
for(i=0; i<a; i++)
printf("%-10s%-50s%-10.2f%-10c\n", std[i].id, std[i].name, std[i].grade, std[i].assess);
}
case 4:
{
printf("Student's name who you want to search: ");
fgets(search, MAX, stdin);
getchar();
for(i=0; i<a; i++)
if(strcasecmp(search, std[i].name)==0)
printf("%-10s%-50s%-10.2f%-10c\n", std[i].id, std[i].name, std[i].grade, std[i].assess);
}
case 5:
break;
default:
{
printf("Please reinsert your choice again\n");
break;
}
}
}while(choice!=5);
return 0;
}
解决方案
这个问题源于一开始\n
没有被消耗scanf
。为了克服我添加的情况while ((c = getchar()) != '\n' && c != EOF);
。
为了摆脱使用\n
后的字符fgets
,我更喜欢使用strcspn。
case 1:
{
do{
printf("How many students you want to add?\n");
scanf("%d", &num);
int c;
while ((c = getchar()) != '\n' && c != EOF);
if(num<0 || num>50)
printf("Your number must be positive or smaller than or equal to 50!\n");
}while(num<0||num>50);
for(i=a; i<num; i++)
{
printf("Student's id No.%d:", i);
fgets(std[i].id, 10, stdin);
std[i].id[strcspn(std[i].id, "\n")] = 0;
printf("Student's name No.%d:", i);
fgets(std[i].name, 50, stdin);
std[i].name[strcspn(std[i].name, "\n")] = 0;
printf("Student's grade No.%d:", i);
scanf("%f", &std[i].grade);
std[i].assess=assess(std[i].grade);
}
a=num;
break;
}
此外,asses
功能可以简化如下。
char assess(double a)
{
if(a < 4.00)
return 'F';
if(a < 6.00)
return 'D';
if(a < 7.00)
return 'C';
if(a < 8.50)
return 'B';
if(a < 10.00)
return 'A';
else
return -1; // the error indicator to be handled.
}
此外,在每个 之后case
,您应该放置break
语句。一目了然开关使用情况。
推荐阅读
- google-apps-script - 如何使用 Google Apps 脚本 (GAS) 创建多个驱动器文件夹
- javascript - Chrome调度KeyboardEvent不起作用
- php - 带有代理到 https 链接的 php curl 请求
- playframework - 当我从集群中删除成员时,Infinispan 8.0.1 崩溃
- python-3.x - OpenCV 分类器错误:(-215) !empty() in function detectMultiScale
- java - 静态初始化,main和premain的执行顺序
- html - 尝试在大型显示器上水平对齐项目,并使用引导程序在小型显示器上垂直对齐项目
- javascript - Semantic UI React:同一个组件中多个 useEffect 调用的问题
- ggplot2 - R:如何制作时间序列中最后(或任何)数据点的小提琴/箱线图?
- ruby-on-rails - 处理“宝石加载错误”时如何安装 Rails