简体   繁体   English

为什么具有字符集格式的 scanf 不在 for 循环中读取输入?

[英]Why doesn't scanf with character set format read input in a for loop?

While trying to get newline character as input using scanf and display it as output as this discussion suggests, I tried the following code,在尝试使用 scanf 获取换行符作为输入并将其显示为此讨论所建议的输出时,我尝试了以下代码,

#include <stdio.h>
void main()
{
    int n;
    printf("Loop:\n");

    scanf("%d",&n);
    for (int i = 0; i < n; ++i)
    {
        char in[28];
        scanf("%27[^\n]%*c",&in);
        printf("%s\n",in);
    }
}

During execution, inside the for loop the input stream doesn't accept any inputs and instead displays n smiley faces.在执行期间,在 for 循环内,输入流不接受任何输入,而是显示 n 个笑脸。 Is this because of the trailing newline character after reading n?这是因为读取 n 后尾随换行符吗?

Beyond the type mismatch, the reason scanf("%27[^\n]%*c",&in);除了类型不匹配,原因scanf("%27[^\n]%*c",&in); does not read extra input from the user is there is a pending newline left by scanf("%d",&n);不读取用户的额外输入是否存在scanf("%d",&n); . . scanf() fails because there is no match for the character set and the newline is not consumed by %*c because the previous mismatch stops the scan. scanf()失败,因为没有匹配字符集并且换行符没有被%*c消耗,因为之前的不匹配停止了扫描。

Here is a modified version:这是修改后的版本:

#include <stdio.h>

int flush_input(void) {
    int c;
    while ((c = getchar()) != EOF && c != '\n')
        continue;
    return c;
}

int main() {
    int n;
    printf("Loop:\n");

    if (scanf("%d", &n) != 1)
        return 1;

    flush_input();
    for (int i = 0; i < n; ++i) {
        char in[28];
        if (scanf("%27[^\n]", in) != 1) {
            // blank line or EOF
            *in = '\0';
        }
        printf("%s\n", in);
        if (flush_input() == EOF)
            break;
    }
    return 0;
}

How to compile any C program as a beginner: What compiler options are recommended for beginners learning C?如何作为初学者编译任何 C 程序:对于学习 C 的初学者,推荐哪些编译器选项?

Following this advise and compiling with gcc gives 2 problems:遵循此建议并使用 gcc 进行编译会出现 2 个问题:

<source>:2:6: error: return type of 'main' is not 'int' [-Wmain]
    2 | void main()
      |      ^~~~
<source>: In function 'main':
<source>:11:21: error: format '%[^
   ' expects argument of type 'char *', but argument 2 has type 'char (*)[28]' [-Werror=format=]
   11 |         scanf("%27[^\n]%*c",&in);
      |                ~~~~~^~      ~~~
      |                     |       |
      |                     char *  char (*)[28]
  • The first reported error is because void main() is an implementation-defined form of main() which isn't suitable for gcc unless you explicitly compile for embedded systems or the like.第一个报告的错误是因为void main()是 main() 的实现定义形式,它不适合 gcc,除非您为嵌入式系统等显式编译。 Switch to int main (void) .切换到int main (void)

  • The second reported error says that the conversion %c expected a parameter of type char* .第二个报告的错误表示转换%c需要一个char*类型的参数。 You gave it a parameter of type char (*)[28] .你给了它一个char (*)[28]类型的参数。 Huh, what is that?咦,那是什么? Well, it is a pointer to an array of 28 char.嗯,它是一个指向 28 个字符的数组的指针。 Not the same thing and not what you want, but what you get if you do &in instead of in .不是同一件事,也不是你想要的,而是如果你做&in而不是in ,你会得到什么。

Luckily, viewing multiple lines of the gcc output gives you the exact location of the bug, after which you will find the bug in seconds:幸运的是,查看多行 gcc 输出可以为您提供错误的确切位置,之后您将在几秒钟内找到错误:

   11 |         scanf("%27[^\n]%*c",&in);
      |                ~~~~~^~      ~~~
      |                     |       |
      |                     expect  BUG HERE FIX ME

Now if you follow the above guidelines, you should be able fix the next trivial bug that the compiler has already found.现在,如果您遵循上述指南,您应该能够修复编译器已经发现的下一个小错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM