使用fscanf读取时包括换行符

时间:2018-10-09 20:33:54

标签: c file scanf stdio

使用fscanf()逐字读取文件时,如何读取(n个可选的)换行符?

我知道我可以使用fgets() + strtok(),但是我的程序特别需要fscanf()

我尝试了以下操作:

fscanf(fp, "%s%[\n]+", buf);

但这根本不起作用。

1 个答案:

答案 0 :(得分:1)

您可以使用以下转换格式来使用和忽略单个换行符:%*1[\n]。它最多消耗一条换行符并将其丢弃。请注意,如果有多个连续的换行符,则只会跳过第一个。还要注意fscanf()将读取一个额外的字节以验证其是否匹配。如果不匹配,该字节将使用ungetc()推回到流中。

如果您使用%*[\n],则fscanf将继续读取流,直到它获得与换行符不同的字节或到达文件末尾为止,这将在处理来自终端的交互式输入时引起令人惊讶的行为。

您的代码fscanf(fp, "%s[\n]", buf);导致未定义的行为,因为您没有为换行符提供目标数组。此外,它还有另一个缺陷,因为您没有指定要存储到buf中的最大字节数,从而导致长字输入出现不确定的行为。

尝试一下:

    char buf[100];
    if (fscanf(" %99s%*1[\n]", buf) == 1) {
        printf("read a word: |%s|\n", buf);
    } else {
        printf("no more words\n");
    }

如果要在缓冲区中包含换行符,则需要将其存储到变量中并手动添加:

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

int main() {
    for (;;) {
        char buf[100];
        char nl[2] = "";
        int n = fscanf(stdin, " %98s%1[\n]", buf, nl);
        if (n > 0) {
            strcat(buf, nl);
            printf("read a word: |%s|\n", buf);
        } else {
            printf("no more words\n");
            break;
        }
    }
    return 0;
}

输入:

Hello word
  I     am   ready    

输出:

read a word: |Hello|
read a word: |word
|
read a word: |I|
read a word: |am|
read a word: |ready|
no more words