使用C中的scanf解析输入
我一直在试图找出如何使用scanf()
遇到很多问题。 它似乎与整数一起使用,相当直接的scanf("%d", &i)
。
我scanf()
问题是在循环中使用scanf()
尝试读取输入。 例如:
do { printf("counter: %d: ", counter); scanf("%c %c%d", &command, &prefix, &input); } while (command != 'q');
-
当我输入一个有效结构的输入,如
c P101
,它似乎再次循环,然后提示我。 即使只有一个,这似乎也会发生:scanf("%c", &c)
在一个循环中。 在再次提示我之前,它会进行两次循环。 是什么让它循环两次,我该如何阻止它?
-
当我输入较少量的输入时,编程上不会有另一个字符或数字,如
q
,按Enter似乎提示我输入更多。 如何让scanf()
处理单字符和双字符条目?
当您输入“ 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()进行解析。
它真的坏了! 我不知道
#include 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---
输出似乎符合罗伯特的答案。
一旦你有包含该行的字符串。 即“C P101”,您可以使用sscanf的解析function。
请参阅: http : //www.cplusplus.com/reference/clibrary/cstdio/sscanf.html
对于问题1,我怀疑你的printf()
有问题,因为没有终止“\ n”。
printf
的默认行为是缓冲输出,直到它有一个完整的行。 这是除非你明确改变stdout
上的缓冲。
对于问题2,你刚刚遇到了scanf()
一个最大问题。 除非您的输入与您指定的扫描字符串完全匹配,否则您的结果将与您的预期完全不同。
如果你有一个选项,你可以忽略scanf()
并进行自己的解析,从而获得更好的结果(以及更少的安全问题)。 例如,使用fgets()
将整行读入字符串,然后处理字符串的各个字段 – 甚至可以使用sscanf()
。
也许使用while循环,而不是do … while循环会有所帮助。 这样,在执行代码之前测试条件。 请尝试以下代码段:
while(command != 'q') { //statements }
此外,如果您提前知道字符串长度,’for’循环可以比’while’循环更容易使用。 动态确定长度也有一些比较棘手的方法。
作为最后的咆哮: scanf()
不会“吮吸”。 它做它做的事,就是这样。 fgets()
非常危险(虽然对于无风险的应用程序很方便),因为它本身不会对输入进行任何检查。 它通常被称为利用点,特别是缓冲区溢出攻击,覆盖未分配给该变量的寄存器中的空间。 因此,如果您选择使用它,请花一些时间进行一些可靠的错误检查/更正。
希望这可以帮助将来的人,因为我认为你现在已经处理好了! ;)