【问题标题】:unknown error the function 'scanf("%[^\n]%*c", &sent);'未知错误函数'scanf("%[^\n]%*c", &sent);'
【发布时间】:2020-03-06 00:24:51
【问题描述】:

言归正传,我是 C 语言的初学者,刚刚在 C 程序中遇到了一种输入字符串的奇怪方法:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

int main() {
    char ch, string[100], sent[100];
    scanf("%c", &ch);
    scanf("%s", &string);
    scanf("%[^\n]%*c", &sent);

    printf("%c\n", ch);
    printf("%s\n", string);
    printf("%s", sent);

    return 0;
}

这是错误:最后一行(句子)不打印,不知道我错在哪里,但在研究中我发现了这段代码:

scanf(" %[^\n]%*c", &sent); //not theres a space before %[^\n]%*c; and then it worked (wtf)

你能解释一下为什么只在其中添加一个空格就可以工作吗?

【问题讨论】:

  • 这是因为每个说明符% 之后的* 告诉scanf 不要存储结果。编译器说“警告C4474:'scanf':为格式字符串传递的参数太多。”
  • @WeatherVane 但是在 "%*[^\n]%*c" 之前放置 1 个空格如何解决所有问题,在放置空间之后代码可以完美运行
  • 我不知道:编译器仍然给出警告。除了:&amp;string&amp;sent 应该是 stringsent 反正。无论如何,如果不说您输入的内容,就无法评论“完美无缺”的含义。
  • 我正在以黑客级别练习此代码,我知道“&”不应该存在,但没有它,他们的编译器会显示错误
  • 您的代码有未定义的行为。它尝试打印一个未初始化的字符串。

标签: c output scanf format-specifiers


【解决方案1】:

格式字符串中的空格 () 导致 scanf 跳过输入中的空格。它通常不需要,因为大多数 scanf 转换在扫描任何内容之前也会跳过空格,但两个不是%c%[ - 所以在%[ 之前使用空格会产生明显的效果。让我们看看你的 3 个 scanf 调用做了什么:

scanf("%c",&ch);           // read the next character into 'ch'
scanf("%s",&string);       // skip whitespace, then read non-whitespac characters
                           // into 'string', stopping when the first whitespace after
                           // some non-whitespace is reached (that last whitespace
                           // will NOT be read, being left as the next character
                           // of the input.)
scanf("%[^\n]%*c",&sent);  // read non-newline characters into 'sent', up until a
                           // newline, then read and discard 1 character
                           // (that newline)

因此,第三个 scanf 将从结束第二个 scanf 的空格开始读取。如果您在格式的开头添加一个空格,它将改为读取并丢弃空格,直到找到一个非空格字符,然后使用该非空格字符开始读入sent

如果结束第二个 scanf 的空格恰好是换行符,也会发生什么情况。在这种情况下,第三个 scanf 将完全失败(因为在换行符之前没有要读取的非换行符)并且什么也不做。将此处的空格添加到第三个 scanf 可确保它不会因换行而失败(它将被丢弃为空格),因此它将始终将某些内容读入 sent,除非达到 EOF。

【讨论】:

  • 您可能还指出&amp;string&amp;sent 上的&amp; 是无害但不正确的,使用转换格式"%99s"" %99[^\n]%*c" 会更安全,以及测试返回值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-06
  • 2018-11-28
  • 1970-01-01
  • 2017-05-02
  • 1970-01-01
  • 1970-01-01
  • 2012-11-10
相关资源
最近更新 更多