代码之家  ›  专栏  ›  技术社区  ›  zxcv

用C语言中的scanf解析输入

  •  10
  • zxcv  · 技术社区  · 16 年前

    我在想如何使用时遇到了很多问题 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) 
      

    2. 当我以编程方式输入较少的输入时,不会有其他字符或数字,例如 q ,按enter键似乎会提示我输入更多。我该怎么去 scanf() 要同时处理单字符和双字符条目?

    5 回复  |  直到 11 年前
        1
  •  19
  •   Robert Gamble    16 年前

    c P101 “程序实际收到” c P101\n “。大多数转换说明符跳过前导空格,包括换行符,但 %c 没有。第一次看到一切,直到“ \n command , " c “读进 prefix ,及“ P P101\n “保留在流中。下次” 存储到命令中 1 1. (从剩余部分开始) 01 \n “下次仍在流中。您可以通过在格式字符串的开头添加空格来解决此问题,该空格将跳过任何前导空格(包括换行符)。

    第二个案例也发生了类似的事情,当你进入“ q q\n 第一次在 第二次读取 阅读,您可以通过在格式字符串的开头添加空格字符来避免再次出现问题。

    更好的方法是使用类似fgets()的方法一次处理一行,然后使用sscanf()进行解析。

        2
  •  1
  •   Federico A. Ramponi    16 年前

    #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---
    

    结果似乎与罗伯特的答案相符。

        3
  •  1
  •   Shanti    16 年前

    获得包含行的字符串后。i、 e.“C P101”,您可以使用sscanf的解析功能。

    见: http://www.cplusplus.com/reference/clibrary/cstdio/sscanf.html

        4
  •  1
  •   Jonathan Leffler    11 年前

    printf() ,因为没有终止“\n”。

    printf 是缓冲输出,直到它有一个完整的行。这是除非您显式更改上的缓冲区 stdout .

    对于问题2,您刚刚遇到了 scanf() . 除非您的输入与您指定的扫描字符串完全匹配,否则您的结果将与您期望的完全不同。

    scanf() 并进行您自己的解析。例如,使用 fgets() sscanf() .

        5
  •  0
  •   Jonathan Leffler    5 年前

    也许使用while循环,而不是do…while循环会有所帮助。这样,在执行代码之前测试条件。 请尝试以下代码段:

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

    此外,如果您提前知道字符串长度,“for”循环比“while”循环更容易使用。还有一些更复杂的方法可以动态确定长度。

    作为最后的咆哮: scanf() 不“吸”,它做它所做的,仅此而已。

    gets() function is very dangerous (尽管对于无风险的应用程序来说很方便),因为它本身不进行任何输入检查。它通常被称为攻击点,特别是缓冲区溢出攻击,覆盖未分配给该变量的寄存器中的空间。因此,如果您选择使用它,请花一些时间进行一些可靠的错误检查/更正。

    fgets() 还是POSIX getline() . 可以从中删除尾随的换行符 string fgets() string[strcspn(string, "\n")] = '\0'; 这工作可靠。