每个输入之后冲洗标准输入 - 这方法并不马车? [英] Flushing stdin after every input - which approach is not buggy?

查看:139
本文介绍了每个输入之后冲洗标准输入 - 这方法并不马车?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

标记Lakata 指出,垃圾无法正常在我的问题我想出了这个定义。我会记住这更新,以避免混乱。

After Mark Lakata pointed out that the garbage isn't properly defined in my question I came up with this. I'll keep this updated to avoid confusions.

我试图让我可以对用户输入的printf提示如之前调用(请输入您的选择:)功能; 遵循 scanf函数,并确保只输入东西后及时将被 scanf函数作为有效输入要扫描

I am trying to get a function that I can call before a prompt for user input like printf("Enter your choice:); followed a scanf and be sure that only the things entered after the prompt would be scanned in by scanf as valid input.

据我可以理解,需要的功能是什么,完全刷新标准输入。这就是我想要的。因此,对于这个功能的目的垃圾是一切都在用户输入即用户提示之前,整个用户的输入。

As far as I can understand the function that is needed is something that flushes standard input completely. That is what I want. So for the purpose of this function the "garbage" is everything in user input i.e. the whole user input before that user prompt.

在使用 scanf()的用C总有额外的输入趴在输入缓冲区的问题。所以我一直在寻找,我每次scanf函数调用之后打电话解决这个问题的功能。我用,的这个并的this 来得到这些答案

While using scanf() in C there is always the problem of extra input lying in the input buffer. So I was looking for a function that I call after every scanf call to remedy this problem. I used this, this, this and this to get these answers

//First approach
scanf("%*[^\n]\n");

//2ndapproach
scanf("%*[^\n]%*c");

//3rd approach
int c;
while((c = getchar()) != EOF) 
    if (c == '\n') 
        break;

全部三远工作,我可以通过打了审讯发现并引用去。但是,在我所有的codeS中使用任何这些之前,我想知道任何这些是否有什么错误?

All three are working as far as I could find by hit-and-trial and going by the references. But before using any of these in all of my codes I wanted to know whether any of these have any bugs?

编辑:

感谢马克Lakata 在第三届一个bug被纠正。我在这个问题纠正它。

Thanks to Mark Lakata for one bug in 3rd. I corrected it in the question.

EDIT2:

杰里棺材回答我测试了code。使用此计划的第一个方法2:块IDE 12.11使用GNU编译器GCC(版本的编译器设置不详)。

After Jerry Coffin answered I tested the 1st 2 approaches using this program in code:blocks IDE 12.11 using GNU GCC Compiler(Version not stated in the compiler settings).

#include<stdio.h>

int main()
{
    int x = 3; //Some arbitrary value
    //1st one
    scanf("%*[^\n]\n");
    scanf("%d", &x);
    printf("%d\n", x);

    x = 3;
    //2nd one
    scanf("%*[^\n]%*c");
    scanf("%d", &x);
    printf("%d", x);
}

我用下面的2个输入

I used the following 2 inputs

第一个测试输入(2换行符,但在垃圾输入中间无空格)

First Test Input (2 Newlines but no spaces in the middle of garbage input)

abhabdjasxd


23
bbhvdahdbkajdnalkalkd



46

对于第一个我得到了由的printf 语句的输出以下

23
46

即。无论codeS工作正常。

i.e. both codes worked properly.

第二个测试输入:(2换行符在垃圾输入中间空格)

Second Test input: (2 Newlines with spaces in the middle of garbage input)

hahasjbas asasadlk


23
manbdjas sadjadja a


46

对于第二个我得到了由的printf 语句的输出以下

23
3

因此​​,我发现,第二个将不采取额外的垃圾输入空格照顾。因此,它不是万无一失对抗垃圾输入。

Hence I found that the second one won't be taking care of extra garbage input whitespaces. Hence, it isn't foolproof against garbage input.

我决定尝试一个 3测试用例(垃圾包括前后非空白字符后换行)

I decided to try out a 3rd test case (garbage includes newline before and after the non-whitespace character)

``
hahasjbas asasadlk


23

manbdjas sadjadja a


46

答案是

3
3

即。双方未能在这个测试用例。

i.e. both failed in this test case.

推荐答案

前两个是微妙的不同:它们读取和忽略所有的字符,直到达到新的线。然后第一个跳过所有连续的白色空间,所以后执行,你看了会非空白。下一个字符

The first two are subtly different: they both read and ignore all the characters up to a new-line. Then the first skips all consecutive white space so after it executes, the next character you read will be non-whitespace.

第二读取和忽略的字符,直到遇到那么一个新的行读取(和丢弃)正是一个或多个字符。

The second reads and ignores characters until it encounters a new-line then reads (and discards) exactly one more character.

的差异将显示,如果您有(例如)双倍行距的文本,如:

The difference will show up if you have (for example) double-spaced text, like:

line 1

line 2

让我们假设你在第1行的中间读的地方如果再执行第一个,你读的将是2号线的L如果执行第二下一个字符,下一个字符,你阅读将是1号线和2号线的新线。

Let's assume you read to somewhere in the middle of line 1. If you then execute the first one, the next character you read in will be the 'l' on line 2. If you execute the second, the next character you read in will be the new-line between line 1 and line 2.

至于第三个,如果我打算做这一切时,我会做这样的事情:

As for the third, if I were going to do this at all, I'd do something like:

int ch;
while ((ch=getchar()) != EOF && ch != '\n')
    ;

...是的,这工作正常 - &放大器;&安培; 强制序列点,所以其左操作数先计算。然后有一个顺序点。然后,当且仅当左边的操作数计算为真正,它计算它的右操作数。

...and yes, this does work correctly -- && forces a sequence point, so its left operand is evaluated first. Then there's a sequence point. Then, if and only if the left operand evaluated to true, it evaluates its right operand.

至于性能差异:因为你要处理的I / O,开始时,几乎没有合理的问题,所有这些都将永远是I / O限制。尽管其明显的复杂性, scanf函数(和公司)通常code,它的被使用,精心优化了使用年限。在这种情况下,手卷循环可能是相当慢一点(例如,如果code为的getchar 没有得到扩展内联),也可以是大约相同的速度。它代表的是显著较快任何机会,唯一的办法是,如果谁写你的标准库的人是不称职的。

As for performance differences: since you're dealing with I/O to start with, there's little reasonable question that all of these will always be I/O bound. Despite its apparent complexity, scanf (and company) are usually code that's been used and carefully optimized over years of use. In this case, the hand-rolled loop may be quite a bit slower (e.g., if the code for getchar doesn't get expanded inline) or it may be about the same speed. The only way it stands any chance of being significantly faster is if the person who wrote your standard library was incompetent.

据可维护性:IMO,任何人谁自称懂C的的知道 scanf函数扫描集转换。这既不新鲜也不火箭科学。如果谁不知道它真的不是一个称职的C程序员。

As far maintainability: IMO, anybody who claims to know C should know the scan set conversion for scanf. This is neither new nor rocket science. Anybody who doesn't know it really isn't a competent C programmer.

这篇关于每个输入之后冲洗标准输入 - 这方法并不马车?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆