解析输入在C的scanf解析输入在C的scanf(Parsing input with scanf

2019-05-09 01:25发布

我一直有一个很大的问题,试图找出如何使用scanf() 。 这似乎很好地工作整数,是相当直截了当scanf("%d", &i)

当我遇到问题时使用scanf()在循环试图读取输入。 例如:

do {
  printf("counter: %d: ", counter);
  scanf("%c %c%d", &command, &prefix, &input);
} while (command != 'q');
  1. 当我像一个有效的结构输入输入c P101 ,它似乎促使我之前再次循环。 这似乎与一个甚至发生:

     scanf("%c", &c) 

    在一个while循环。 再次提示我之前它会做循环两次。 是什么使得它循环两次,我该如何阻止它?

  2. 当我在编程不会有另一个字符或数字,如输入量少进入q ,按enter似乎提示我输入更多。 如何获得scanf()来处理单,双字条目?

Answer 1:

当你进入“ c P101 ”节目实际收到“ c P101\n ”。 大部分的转换说明跳过前导空白包括换行,但%c没有。 周围的一切了无菌的“第一次\n ”被读取时,第二次围绕“\ n”被读入command ,“ c ”被读入prefix ,和“ P ”被留下这不是一个号码,以便在转换失败和“ P101\n ”被留在流。 下一次“ P ”被存储到命令,“ 1 ”被存储到前缀,以及1 (从剩余的“ 01 ‘)被存储到输入用’ \n ”仍然在流为下一次。 您可以通过在格式字符串,这将跳过任何前导空格,包括换行的开头放一个空间解决此问题。

一个类似的事情也发生第二种情况,当你输入“ q ”,“ q\n ”输入到流,围绕“首次q ”被读取时,第二次“ \n ”被读取,仅在第三个电话是继“ q ”阅读,您可以通过在格式字符串的开头添加一个空格字符再次避免此问题。

一个更好的办法来做到这一点是使用类似与fgets()来处理在一个时间线,然后使用的sscanf()做解析。



Answer 2:

这真的碎了! 我不知道它

#include <stdio.h>

int main(void)
{
    int counter = 1;
    char command, prefix;
    int input;

    do 
    {
        printf("counter: %d: ", counter);
        scanf("%c %c%d", &command, &prefix, &input);
        printf("---%c %c%d---\n", command, prefix, input);
        counter++;
    } while (command != 'q');
}
counter: 1: a b1
---a b1---
counter: 2: c d2
---
 c1---
counter: 3: e f3
---d 21---
counter: 4: ---e f3---
counter: 5: g h4
---
 g3---

输出似乎适合与罗伯特的回答。



Answer 3:

一旦你有一个包含行的字符串。 即“C P101”,你可以使用的sscanf的解析能力。

请参阅: http://www.cplusplus.com/reference/clibrary/cstdio/sscanf.html



Answer 4:

问题1,我怀疑你有你的问题printf()因为没有终止“\ n”。

的默认行为printf是缓冲输出,直到它有一个完整的线。 也就是说,除非你明确地改变缓冲stdout

对于问题2,你刚才打的有一个最大的问题scanf() 。 除非你输入你所指定的扫描字符串完全匹配,你的结果将是没有像你期望的。

如果你有一个选项,你就必须通过忽略更好的结果(和更少的安全问题) scanf() ,做你自己的分析。 例如,使用fgets()来读取整个行成一个字符串,然后处理该字符串的各个字段-甚至使用sscanf()



Answer 5:

或许用while循环,而不是一个do ... while循环会有所帮助。 这样的条件是代码的执行之前进行测试。 试试下面的代码片段:

 while(command != 'q')
    {
        //statements
    }

另外,如果你事先知道字符串的长度,“为”循环可以更容易比“而”循环工作。 也有一些棘手的方式来动态地确定长度为好。

作为最后的咆哮: scanf()没有“吸”。 它做它做什么,这是所有。 fgets()是非常危险的(虽然方便了无风险的应用程序),因为它本身并不做任何输入检查。 这是非常俗称利用一个点,特别缓冲区溢出攻击,在不分配给该变量寄存器覆盖空间。 因此,如果您选择使用它,花一些时间把一些固定误差检测/校正英寸

希望这可以帮助别人的未来,因为我相信你已经得到它现在处理! ;)



文章来源: Parsing input with scanf in C
标签: c scanf