C语言 使用 fscanf() 与 fgets() 和 sscanf()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22330969/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using fscanf() vs. fgets() and sscanf()
提问by ankush981
In the book Practical C Programming, I find that the combination of fgets()and sscanf()is used to read input. However, it appears to me that the same objective can be met more easily using just the fscanf()function:
在这本书中实用的C语言编程,我发现的组合fgets()和sscanf()用于读取输入。但是,在我看来,仅使用该fscanf()函数就可以更轻松地实现相同的目标:
From the book (the idea, not the example):
从书中(想法,而不是例子):
int main()
{
int age, weight;
printf("Enter age and weight: ");
char line[20];
fgets(line, sizeof(line), stdin);
sscanf(line, "%d %d", &age, &weight);
printf("\nYou entered: %d %d\n", age, weight);
return 0;
}
How I think it should be:
我认为它应该是这样的:
int main()
{
int age, weight;
printf("Enter age and weight: ");
fscanf(stdin, "%d %d", &age, &weight);
printf("\nYou entered: %d %d\n", age, weight);
return 0;
}
Or there is some hidden quirk I'm missing?
还是我遗漏了一些隐藏的怪癖?
回答by FatalError
There are a few behavior differences in the two approaches. If you use fgets()+ sscanf(), you must enter both values on the same line, whereas fscanf()on stdin(or equivalently, scanf()) will read them off different lines if it doesn't find the second value on the first line you entered.
这两种方法存在一些行为差异。如果使用fgets()+ sscanf(),则必须在同一行中输入两个值,而fscanf()on stdin(或等效地,scanf())如果在您输入的第一行中找不到第二个值,则会从不同的行读取它们。
But, probably the most important differences have to do with handling error cases and the mixing of line oriented input and field oriented input.
但是,最重要的区别可能与处理错误情况以及面向行的输入和面向字段的输入的混合有关。
If you read a line that you're unable to parse with sscanf()after having read it using fgets()your program can simply discard the line and move on. However, fscanf(), when it fails to convert fields, leaves all the input on the stream. So, if you failed to read the input you wanted, you'd have to go and read all the data you want to ignore yourself.
如果您sscanf()在使用fgets()程序阅读后阅读了无法解析的行,则可以简单地丢弃该行并继续。但是,fscanf()当它无法转换字段时,会将所有输入留在流中。因此,如果您未能读取您想要的输入,您必须自己去读取您想要忽略的所有数据。
The other subtle gotcha comes in if you want to mix field oriented (ala scanf()) with line oriented (e.g. fgets()) calls in your code. When scanf()converts an intfor example, it will leave behind a \non the input stream (assuming there was one, like from pressing the enter key), which will cause a subsequent call to fgets()to return immediately with only that character in the input. This is a really common issue for new programmers.
如果您想在代码中混合面向字段 (ala scanf()) 和面向行 (例如fgets()) 的调用,则会出现另一个微妙的问题。例如,当scanf()转换 an 时int,它会\n在输入流上留下 a (假设有一个,比如按下回车键),这将导致后续调用fgets()立即返回输入中只有该字符。对于新程序员来说,这是一个非常普遍的问题。
So, while you are right that you can just use fscanf()like that, you may be able to avoid some headaches by using fgets()+ sscanf().
因此,虽然您可以这样使用fscanf()是对的,但您可以通过使用fgets()+来避免一些麻烦sscanf()。
回答by pmg
The problem with only using fscanf()is, mostly, in error management.
仅使用的问题fscanf()主要在于错误管理。
Imagine you input "51 years, 85 Kg" to both programs.
想象一下,您在两个程序中都输入了“ 51 年,85 公斤”。
The first program fails in the sscanf()and you still have the lineto report errors to the user, to try a different parsing alternative, to something;
第一个节目的失败sscanf(),你仍然有line报告错误给用户,尝试不同的解析替代,以东西;
The second program fails at years, ageis usable, weightis unusable.
第二个程序在years失败,age可用,weight不可用。
Remeber to always check the return value of *scanf()for error checking.
请记住始终检查 的返回值以*scanf()进行错误检查。
fgets(line, sizeof(line), stdin);
if (sscanf(line, "%d%d", &age, &weight) != 2) /* error with input */;
Edit
编辑
With your first program, after the error, the input buffer is clear; with the second program the input buffer starts with YEAR...
使用你的第一个程序,在错误之后,输入缓冲区是清除的;对于第二个程序,输入缓冲区以 YEAR 开头...
Recovery in the first case is easy; recovery in the second case has to go through some sort of clearing the input buffer.
在第一种情况下恢复很容易;第二种情况下的恢复必须通过某种方式清除输入缓冲区。
回答by chux - Reinstate Monica
There is no difference between fscanf()versus fgets()/sscanf()when:
fscanf()与fgets()/ sscanf()when之间没有区别:
- Input data is well-formed.
- 输入数据格式良好。
Two types of errors occur: I/O and format.
fscanf()simultaneously handles these two error types in one function but offer few recovery options. The separatefgets()andsscanf()allow logical separation of I/O issues from format ones and thus better recovery.
发生两种类型的错误:I/O 和格式。
fscanf()在一个函数中同时处理这两种错误类型,但提供的恢复选项很少。分离fgets()并sscanf()允许将 I/O 问题与格式问题进行逻辑分离,从而更好地恢复。
- Only 1 parsing path.
- 只有 1 个解析路径。
Separating I/O from scanning allows multiple
sscanf()options. Should a given scanning of a buffer not realize the desired results, othersscanf()with different formats are available.
将 I/O 与扫描分开允许多个
sscanf()选项。如果给定的缓冲区扫描没有实现预期的结果,sscanf()则可以使用其他不同的格式。
- No embedded
'\0'.
- 没有嵌入
'\0'。
Rarely does
'\0'occurs, but should one occur,sscanf()will not see it as scanning stops with its occurrence, whereasfscanf()continues.
很少
'\0'发生,但如果发生,sscanf()将不会看到它,因为扫描会随着它的发生而停止,而会fscanf()继续。
In all cases, check results of all three functions.
在所有情况下,检查所有三个函数的结果。

