C - scanf等待,直到可以评估格式的所有部分

时间:2013-02-26 06:30:22

标签: c scanf

我没有太多时间,而且很多关于stdin的内容只会提出比现阶段更多的问题。我希望测试使用scanf的多个实例传递的多种类型的命令。

如果我这样做:

char inputChar;
char inputChars[15] = { NULL };
int inputInt;
double inputDec;

if(scanf("%c %d %lf",&inputChar,&inputInt,&inputDec) == 3) {
    ...
}
else if(scanf("%c %d %s",&inputChar,&inputInt,&inputChars) == 3) {
    ...
}
else if(scanf("%c %d",&inputChar,&inputInt) == 2) {
    ...
}
else if(scanf("%c",&inputChar) == 1) {
    ...
}
else {
    ...
}

然后键入单个字符并按Enter键,控制台会等到我输入另一个值,然后再评估是否匹配。

更新

这似乎工作得很好,除非它希望您在使用时输入完美。如果用户键入aa,然后在按Enter键之前将其更改为a 10,则会与第4次评估相匹配。这有两个原因:

  1. 因为如果正确捕获输入,应该匹配第3个;和
  2. 因为如果aa应该被过滤到第5次评估中。
  3. 修订代码:

    char input[50] = { NULL };
    
    char inputChar = NULL;
    char inputChars[15] = { NULL };
    int inputInt;
    double inputDec;
    
    printf("Input String:\n>");
    
    fgets(input,sizeof(input),stdin);
    
    if(sscanf(input,"%c%d %lf",&inputChar,&inputInt,&inputDec) == 3) { }
    else if(sscanf(input,"%c%d%s",&inputChar,&inputInt,&inputChars) == 3) { }
    else if(sscanf(input,"%c%d",&inputChar,&inputInt) == 2) { }
    else if(sscanf(input,"%c",&inputChar) == 1) { }
    else { }
    

    做这样的事情表明退格没有被过滤掉:

    for(int i=0;i<50;i++) {
        if(input[i] == (char) 10) { break; }
        printf("\n%c %d",(char) input[i],(int) input[i]);
    }
    

    因此看起来fgets不在图片中。

3 个答案:

答案 0 :(得分:2)

语句按顺序执行。所以它是第一个等待更多输入的scanf调用。如果输入与第一个呼叫不匹配,则下一个scanf呼叫将全部开始,等待输入。等等。

相反,您应该使用fgets来阅读整行,然后在该行上使用sscanf

答案 1 :(得分:1)

请解释“清除输入缓冲区”的含义。你的意思是_flushall在它们发生之前擦除了我的击键吗?怎么会这样呢?也许你的意思是你已经从线上读过了你需要的数据,而你并不关心线路的其余部分。在这种情况下,我假设您希望“阅读并丢弃所有字符,包括下一个换行符”。我有一个便携式机制来做到这一点:

for (int c = getchar(); c >= 0 && c != '\n'; c = getchar());

您可能还希望阅读this related answer

编辑:我刚刚发现你想要的行为可能表达如下:

char inputChar;
char inputChars[15] = { NULL };
int inputInt;
double inputDec;
int x = scanf("%c%d", &inputChar, &inputInt);

if (x == 2 && scanf("%lf",&inputDec) == 1) {
    ...
}
else if (x == 2 && scanf("%14s", inputChars) == 1) {
    ...
}
else {
    ...
}

答案 2 :(得分:0)

可能不是最好的方法,但它有效。

使用iostream库运行getline(std::cin,input);来捕获std::string input的输入,然后在sscanf上多次使用input.c_str()