为什么printf只打印字符串中的第一个单词?

3

我对C编程还比较新,所以我正在使用fgets()和sscanf()读取文件数据。我设置了一个非常简单的实验:

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

main()
{
    char szInputBuffer[100];
    FILE *pFile;
    char szInput[100];
    int i;

    pFile = fopen("MyFile.txt", "r");
    printf("This is the input: \n\n");

    for (i = 0; i <= 2; ++i)
    {
        fgets(szInputBuffer, 100, pFile);
        sscanf(szInputBuffer, "%s", szInput);
        printf("%s", szInput);
    }
}

我正在读取 MyFile.txt 文件,它包含如下内容:

This is more input.
The next line of Input.
More input here.

然而,我的输出是:
This is the input:
ThisTheMore

每一行的第一个单词是什么。我发现,当我在printf语句中添加第二个%s时,如下所示:

printf("%s%s", szInput);

我要达到预期的输出:
This is the input:
This is more input.
The next line of Input.
More input here.

有人能给我解释一下吗?我从未听说过使用第二个占位符来获取整个字符串。我在这里找不到任何有助于解决我的问题的东西。我在课堂上看到了一些示例程序,只在打印语句中使用一个%s,整个字符串就被打印出来了。谢谢帮助好奇的程序员!

附言:我正在运行Ubuntu 14.04 LTS,使用Geany IDE。我知道你们中的一些人会问到这个。


sscanf 中的 %s 格式说明符表示读取第一个单词。如果您想打印整行,则可以跳过该步骤。 - M.M
printf 中给出比后续参数更多的格式说明符会导致未定义的行为;在此之后发生的事情你无法真正理解。 - M.M
1
根据我的了解,你使用sscanf是不必要的。fgets调用将从文件中检索文本。我会放弃sscanf并打印出szInputBuffer。 - user3647894
我知道这一点,但你能解释一下为什么在printf语句中执行%s%s也可以工作吗? - Alejandro Zapien
1个回答

3
sscanf(szInputBuffer, "%s", szInput);

格式说明符%s获取字符串,直到遇到空格或换行符,因此您只能获得一个单词。为了获取整行,请在fgets()后将字符串设置为null终止,因为fgets()带有换行符并打印出该字符串。

scanf()的手册说%s

匹配非空白字符序列;下一个指针必须是足够长以容纳输入序列和终止空字节('\0')的字符数组指针,此空字节会自动添加。输入字符串停止于空格或最大字段宽度,以先到者为准。

请执行

size_t n;
fgets(szInputBuffer, 100, pFile);
n = strlen(szInputBuffer);
if(n>0 && szInputBuffer[n-1] == '\n')
 szInputBuffer[n-1] = '\0';
 printf("%s\n",szInputBuffer);

如果你想将一行文本分成多个字符串,并打印出每个单词,那么可以使用以空格为分隔符的strtok()
如果您看到
printf("%s%s", szInput);

如果在编程中使用了未定义的行为,则无法预测程序的运行结果。printf()函数要求格式说明符的数量与需要输出的值的数量相匹配。请注意,即使类型不匹配,其行为仍是未定义的。


我对%s有一定的了解,但我不明白为什么使用%s%s会生成正确的输出。这是C语言中的一个特性吗?你能给我解释一下吗? - Alejandro Zapien
@AlejandroZapien 我不明白你所说的 %s %s,那么就必须有两个变量来扫描你的值,基本上 %s 正在执行它的操作,因此由于有一个空格,它停止了扫描。 - Gopi
如果我使用printf("%s%s", szInput);,它会以某种方式生成我想要的确切输入。我鼓励你复制代码,运行它,然后修改printf为"%s%s"并再次运行它。无论出于何种原因,它都能正常工作。为什么会这样呢? - Alejandro Zapien
嗯...好的,谢谢你。根据你的回答和其他(非常棒的!)SOF社区的意见,我现在可以看到这个概念背后的推理和逻辑了。谢谢大家! - Alejandro Zapien

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接