打印scanf输入,可能来自忽略的非字母之间

时间:2018-01-14 08:06:07

标签: c scanf

如何打印所有阵列?现在,阵列将打印到最后一部分,所以如果我输入:

hel'lo hi

将输出

hel
lo 

但不是hi。 这是代码:

    char in[1000];
    printf("read these lines: ");
    while(scanf("%29[a-zA-Z]%*[^a-zA-Z]",in)==1){
        printf("%s\n",in);
    }       

1 个答案:

答案 0 :(得分:0)

使用scanf正确解析字符串可能非常棘手,这就是为什么(根据我的个人经验)很少使用它。

为什么你的代码显然失败的原因可能会变得清晰,如果不是以交互方式运行程序,我们会将数据传输到其中。

$ printf "%s" "hel'lo hi" | ./scanf                                                                                                                                          
read these lines: hel
lo
hi

helread these lines:放在同一条线上放一点烦恼,程序按照您的意图运作。

原因是,scanf尝试消耗尽可能多的字符,直到遇到一个字符,该字符不再与格式字符串匹配或者到达输入流的末尾。

我们将两个指令%29[a-zA-Z]标记为 A %*[^a-zA-Z]以及 B

如果您将数据传输到您的程序中,以下数据将显示在stdin

'h' 'e' 'l' '\'' 'l' 'o' ' ' 'h' 'i' <EOF>
----------- ---- ------- --- ------- -----
     A       B      A     B     A     EOF
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~ ~~~~~~~~~~~~~
    1st call       2nd call    3rd call 

在第一个循环期间,scanf消耗'h' 'e' 'l' '\'',因为此时后面的字符l与格式字符串不匹配。然后,我们有第二次运行,直到'h',最后一次运行,结束过早(不使用 B )。

如果您以交互方式运行程序,我们会遇到以下情况:

'h' 'e' 'l' '\'' 'l' 'o' ' ' 'h' 'i' '\n' <scanf blocks>
----------- ---- ------- --- ------- -----? // Maybe B can continue
     A       B      A     B     A     B   
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~ ~~~~~~~~~~~~~
    1st call       2nd call    3rd call 

scanf只返回两次然后阻止,因为可能会有更多数据出现,可以匹配 B

我们可以尝试以格式字符串切换指令,以便首先使用不需要的数据%*[^a-zA-Z]%29[a-zA-Z],这样我们也可以解析像";hel;lo"这样的输入,但是因为{{ 1}}指令匹配非空字符序列,原始示例%[不再有效。

为了正确解决这个问题,在处理每个角落的情况下,我们必须采用不同的方法并使用两个不同的"hel'lo hi"调用,一个消耗不需要的数据,另一个消耗真实数据。我也增加了调用scanf的精度,因为这是缓冲区的大小。为什么要保留1000个字节并仅使用29?

1000