c - 用户输入被跳过
问题描述
仍然通过 C Programming Absolute Beginner's Guide。
我在关于结构的例子中,我无法弄清楚出了什么问题。当我编译并运行代码时,前两个问题运行良好,但在提示“这本书花了多少钱?”后,当我输入这个问题时,接下来的两个问题一起发布。我不知道为什么。我想我写的代码如书中所示。我在网上读到,gets 不是代码,但我现在不知道为什么。任何指导将再次不胜感激!
//This header file defines a structure for information about a book
struct bookInfo {
char title[40];
char author[25];
float price;
int pages;
};
/*This program gets the bookInfo structure by including structurePractice.h
and asks the user to fill in three structures and then prints them*/
//First, include the header file
#include "structurePractice.h"
#include <stdio.h>
int main()
{
int ctr;
struct bookInfo books[3]; //Array of 3 structure variables
//Get information about each book from the user
for (ctr = 0; ctr < 3; ctr++)
{
printf("What is the name of the book #%d?\n", (ctr+1));
gets(books[ctr].title);
puts("Who's is the author? ");
gets(books[ctr].author);
puts("How much did the book cost? ");
scanf(" $%f", &books[ctr].price);
puts("How many pages are in the book? ");
scanf(" %d", &books[ctr].pages);
getchar(); //Clears last newline for next loop
}
//Print a header line and then loop through and print the info
printf("\n\nHere is the collection of books: \n");
for (ctr = 0; ctr < 3; ctr++)
{
printf("#%d: %s by %s", (ctr+1), books[ctr].title, books[ctr].author);
printf("\nIt is %d pages and costs $%.2f", books[ctr].pages, books[ctr].price);
printf("\n\n");
}
return (0);
}
解决方案
你的scanf
.
scanf(" $%f", &books[ctr].price);
^
|
here
这表示您想要 a$
后跟一个十进制数。如果用户不输入美元符号,scanf 将不读取任何内容。输入将保留在输入缓冲区中。它将由下一个阅读scanf
。
这是许多问题scanf
之一。因为scanf
混淆了读取输入和解析输入,如果输入与预期格式不匹配,它将保留在输入缓冲区中。fgets
相反,使用(not gets
) 和.分别读取和解析sscanf
。检查输入是否被读取也很重要,否则books[ctr].price
将包含垃圾。
// Declare a buffer once outside the loop. Reuse it for each fgets call.
// BUFSIZ is a constant for the natural I/O buffer size of your platform.
char buf[BUFSIZ];
puts("How much did the book cost? ");
// Read only as much as the buffer can handle. This is what makes fgets safe,
// and gets unsafe.
fgets(buf, sizeof(buf), stdin);
// sscanf returns the number of items matched. Check if they all matched.
if( sscanf(buf, " %f", &books[ctr].price) != 1) {
printf("Sorry, '%s' doesn't look like a price.", buf);
// Set it to something or else it will be garbage.
books[ctr].price = 0;
}
一个真正的程序会循环直到它得到有效的输入。重要的是读取缓冲区,然后解析它,并检查解析是否有效。稍后您可能会编写一个小函数来打包此提示代码。
推荐阅读
- node.js - 如何处理用户无法发布两次
- sql-server - 保存维护计划失败-无效类字符串错误-SQL Server 2017
- javascript - React 材料表不会再过滤也不会分页
- html - 具有相对和固定属性的内容流问题
- html - Go 默认servemux的奇怪错误神奇地消失了
- python - Django 模板中的 if 和 else 语句
- sql-server - 在非规范化表中分组
- swift - 在 Swift、XCode 12 中将双精度数舍入到小数点后 2 位
- regex - 正则表达式 set =self 以逗号分隔的字符串
- javascript - 如何在 JSX 中结合 toLocaleString() 和 toFixed(2)?