使用 gets 时我的输入被跳过
My inputs are getting skipped when using gets
我无法为循环 i = 2
和 i = 3
的书的 name
输入内容。
它正在被跳过。 i = 1
的第一个输入是 运行 绝对没问题。
我的代码:
#include<stdio.h>
typedef struct book
{
char name[100];
float price;
int pages;
}bk;
int main(void)
{
int i;
bk b[100];
// b1, b2, b3;
for(i=1;i<=3;i++)
{
printf("Enter name of book %d: ",i);
gets(b[i].name);
printf("Enter price of book %d: ",i);
scanf("%f",&b[i].price);
printf("Enter pages of book %d:",i);
scanf("%d",&b[i].pages);
}
printf("\nYour inputs are:");
for(i=1;i<=3;i++)
{
printf("\nName of book %d: %s",i,b[i].name);
printf("\nPrice of book %d: %f",i,b[i].price);
printf("\nPages of book %d: %d",i,b[i].pages);
}
return 0;
}
我应该如何解决这个问题?
您需要记住的第一件事是永远不要再使用 gets
,更多的是 here。
第二个是不要混用gets
(或者说fgets
,你应该用它来代替gets
)和scanf
.
问题的根源在于,在第二个循环中,gets
读取循环结束时 scanf
留在缓冲区中的换行符,看起来好像被跳过,它不是,如果你打印 b[2].name
你会看到它有一个换行符。
您的代码应该更像这样:
void clear_buffer(){ //helper function to clear buffer when needed
int c;
while((c = getchar()) != '\n' && c != EOF){}
printf("Bad input, try again: ");
}
//...
int main(void)
{
int i;
bk b[100];
for (i = 0; i < 3; i++)
{
printf("Enter name of book %d: ", i);
while(scanf(" %99[^\n]", b[i].name) != 1){ // mind the space before specifer
clear_buffer();
}
printf("Enter price of book %d: ", i);
while(scanf("%f", &b[i].price) != 1){
clear_buffer(); // if the value was not parsed correctly, ask again
}
printf("Enter pages of book %d:", i);
while(scanf("%d", &b[i].pages) != 1){
clear_buffer();
}
}
//...
//rest of the code
}
代码有一些改进:
使用scanf(" %99[^\n]", b[i].name)
确保不会有缓冲区溢出,它最多读取99个字符,为空终止符保留一个space,这是一些gets
做不到,这就是为什么它被从语言中删除的原因,虽然有些编译器仍然支持它,但我无法想象为什么。
我正在检查 scanf
是否真的解析了值,如果没有,假设有人输入了一个字符而不是数字,它再次询问,而不是进入无限循环这就是以前会发生的事情。
for (i = 0; i < 3; i++)
确保数组是从索引 0 填充的,按照你的方式,它不会使用数组的第一个元素,你必须修复printf
因此..
您正在从 stdin 读取一些垃圾,您需要使用 setbuf(stdin, NULL);
清理 stdin。而为了显示价格你只需要 2 位小数,你的程序将是这样的:
#include<stdio.h>
typedef struct book
{
char name[100];
float price;
int pages;
}bk;
int main(void)
{
int i;
bk b[100];
// b1, b2, b3;
for(i=1;i<=3;i++)
{
printf("Enter name of book %d: ",i);
setbuf(stdin, NULL);
gets(b[i].name);
printf("Enter price of book %d: ",i);
scanf("%f",&b[i].price);
printf("Enter pages of book %d:",i);
scanf("%d",&b[i].pages);
}
printf("\nYour inputs are:");
for(i=1;i<=3;i++)
{
printf("\nName of book %d: %s",i,b[i].name);
printf("\nPrice of book %d: %.2f",i,b[i].price);
printf("\nPages of book %d: %d",i,b[i].pages);
}
return 0;
}
我无法为循环 i = 2
和 i = 3
的书的 name
输入内容。
它正在被跳过。 i = 1
的第一个输入是 运行 绝对没问题。
我的代码:
#include<stdio.h>
typedef struct book
{
char name[100];
float price;
int pages;
}bk;
int main(void)
{
int i;
bk b[100];
// b1, b2, b3;
for(i=1;i<=3;i++)
{
printf("Enter name of book %d: ",i);
gets(b[i].name);
printf("Enter price of book %d: ",i);
scanf("%f",&b[i].price);
printf("Enter pages of book %d:",i);
scanf("%d",&b[i].pages);
}
printf("\nYour inputs are:");
for(i=1;i<=3;i++)
{
printf("\nName of book %d: %s",i,b[i].name);
printf("\nPrice of book %d: %f",i,b[i].price);
printf("\nPages of book %d: %d",i,b[i].pages);
}
return 0;
}
我应该如何解决这个问题?
您需要记住的第一件事是永远不要再使用 gets
,更多的是 here。
第二个是不要混用gets
(或者说fgets
,你应该用它来代替gets
)和scanf
.
问题的根源在于,在第二个循环中,gets
读取循环结束时 scanf
留在缓冲区中的换行符,看起来好像被跳过,它不是,如果你打印 b[2].name
你会看到它有一个换行符。
您的代码应该更像这样:
void clear_buffer(){ //helper function to clear buffer when needed
int c;
while((c = getchar()) != '\n' && c != EOF){}
printf("Bad input, try again: ");
}
//...
int main(void)
{
int i;
bk b[100];
for (i = 0; i < 3; i++)
{
printf("Enter name of book %d: ", i);
while(scanf(" %99[^\n]", b[i].name) != 1){ // mind the space before specifer
clear_buffer();
}
printf("Enter price of book %d: ", i);
while(scanf("%f", &b[i].price) != 1){
clear_buffer(); // if the value was not parsed correctly, ask again
}
printf("Enter pages of book %d:", i);
while(scanf("%d", &b[i].pages) != 1){
clear_buffer();
}
}
//...
//rest of the code
}
代码有一些改进:
使用
scanf(" %99[^\n]", b[i].name)
确保不会有缓冲区溢出,它最多读取99个字符,为空终止符保留一个space,这是一些gets
做不到,这就是为什么它被从语言中删除的原因,虽然有些编译器仍然支持它,但我无法想象为什么。我正在检查
scanf
是否真的解析了值,如果没有,假设有人输入了一个字符而不是数字,它再次询问,而不是进入无限循环这就是以前会发生的事情。for (i = 0; i < 3; i++)
确保数组是从索引 0 填充的,按照你的方式,它不会使用数组的第一个元素,你必须修复printf
因此..
您正在从 stdin 读取一些垃圾,您需要使用 setbuf(stdin, NULL);
清理 stdin。而为了显示价格你只需要 2 位小数,你的程序将是这样的:
#include<stdio.h>
typedef struct book
{
char name[100];
float price;
int pages;
}bk;
int main(void)
{
int i;
bk b[100];
// b1, b2, b3;
for(i=1;i<=3;i++)
{
printf("Enter name of book %d: ",i);
setbuf(stdin, NULL);
gets(b[i].name);
printf("Enter price of book %d: ",i);
scanf("%f",&b[i].price);
printf("Enter pages of book %d:",i);
scanf("%d",&b[i].pages);
}
printf("\nYour inputs are:");
for(i=1;i<=3;i++)
{
printf("\nName of book %d: %s",i,b[i].name);
printf("\nPrice of book %d: %.2f",i,b[i].price);
printf("\nPages of book %d: %d",i,b[i].pages);
}
return 0;
}