【问题标题】:reading two long sentences using scanf使用 scanf 读取两个长句子
【发布时间】:2017-06-07 08:50:00
【问题描述】:

我想使用 scanf() 从输入中读取两个长句子,它们在两个新行中。

代码:

int main() {
    char a[100], b[100];
    scanf("%[^\n]s", a);
    scanf("%[^\n]s", b);
    printf("%s\n%s", a, b);
}

输入:

she is beautiful
That is a flower

输出:

she is beautiful

scanf() 语句未读取第二个输入。

如何解决?

【问题讨论】:

  • "%[^\n]s" --> "%99[^\n]%*c"
  • scanf() 不太好用,也许你应该试试fgets()getline() (非标准:sick:)。
  • 你为什么要scanf 而不是例如fgets?
  • @BLUEPIXY 如果输入以换行符开头,该版本将失败
  • @Meenakshiyegu 两个长句之间有空行吗?

标签: c string scanf


【解决方案1】:

这需要一个正确的答案。如果您坚持使用scanf(),那么只有一种格式字符串是安全并且可以为所欲为:

int main() {
    char a[100] = "";
    char b[100] = "";
    scanf("%99[^\n]%*c", a);
    scanf("%99[^\n]%*c", b);
    printf("%s\n%s", a, b);
}

在您的原始字符串中,[^\n]s 是错误的,因为 [^\n] 本身就是一个转换说明符,匹配除换行符以外的任何内容。所以后面不应该有s

下一个更改是前面的99。这可确保最多转换99 字符——加上一个用于终止0 的字节,您的数组中正好有100 个可用字符。否则,如果用户输入超过 99 个字符,您的缓冲区就会溢出。

最后的更改是追加%*c%c 将匹配任何字符,在这种情况下,匹配%[^\n] 后留下的换行符。但是你对它不感兴趣,你只是想消费它。这就是* 的用途,它会丢弃匹配的结果。


如果可以的话,像这样使用fgets(),在这种情况下使用起来要简单得多:

int main() {
    char a[100] = "";
    char b[100] = "";
    fgets(a, 100, stdin);
    fgets(b, 100, stdin);

    // if needed, strip newlines, e.g. like this:
    size_t n = strlen(a);
    if (n && a[n-1] == '\n') a[--n] = 0;
    n = strlen(b);
    if (n && b[n-1] == '\n') b[--n] = 0;


    printf("%s\n%s", a, b);
}

【讨论】:

  • 缓冲区溢出怎么办?用户输入的字符串大于 100
  • @VidorVistrom 我认为在我对scanf()fgets() 的回答中已对此进行了解释,这就是第二个参数的用途。
  • 如果用户输入的值大于 100 个字符,它会自动将其分配给另一个变量。100 用于第一个变量。如果超过 100,包括 null,其他变量将获得超出的字符
  • 把这个输入你的程序啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
  • @VidorVistrom 这可能是一个很好的问题。您看到的结果不是 缓冲区溢出,而是对 scanf()fgets() 的第二次调用继续读取第一次调用停止的位置,因为在字节限制内没有换行符被阅读。对于一个健壮的程序,您必须检查您是否真的阅读了整行。这是可能的,但超出了 this 问题的范围。
【解决方案2】:

您可以使用fgets。这可能对你有用。

#include <stdio.h>
#include <stdint.h>

int main() {
    char a[100], b[100];

    if (fgets(a, sizeof a, stdin) == NULL) {
        puts("fgets error");
        return -1;
    }

    if (fgets(b, sizeof b, stdin) == NULL) {   //Read blank lines 
        puts("fgets error");
        return -1;
    }

    if (fgets(b, sizeof b, stdin) == NULL) {
        puts("fgets error");
        return -1;
    }

    printf("%s\n%s", a, b);

    return 0;
}

【讨论】:

  • OP 对输入模棱两可忘记我所说的你可以删除对 fgets() 的第三次调用。在 main 中返回 -1 很奇怪,最好返回 1
  • @Stargateur 感谢您的建议。我修改了答案。
  • @YunbinLiu printf("%s%s",a,b);在没有 '\n' 的新行中打印两个句子,所以 fgets 将 '\n' 读取为一个字符
  • @Meenakshiyegu 感谢您的建议。但这取决于你想要的输出格式。
【解决方案3】:

这样使用

int main(){

    char a[100];

    while (scanf("%[^\n]%*c", a)==1) {
     printf("%s\n",a); 
    }
    return 0;
  }

【讨论】:

  • 不起作用:ideone.com/x8k4XM,缓冲区溢出漏洞。
  • 需要再输入一次才能获得下一行 - 试试看。我
  • 如果第一个字符是'\n',则不打印任何内容。
  • \n 是换行符。如果第一个字符是 \n 则第一行不包含任何内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-19
  • 1970-01-01
  • 1970-01-01
  • 2013-07-04
  • 1970-01-01
  • 1970-01-01
  • 2022-12-19
相关资源
最近更新 更多