Unix C 文件,scanf 忽略空格

Posted

技术标签:

【中文标题】Unix C 文件,scanf 忽略空格【英文标题】:Unix C files , scanf is ignoring whitespace 【发布时间】:2021-12-19 00:33:45 【问题描述】:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>

void main (int argc, char* arcv[]) 
    int fd, quest_num, i, j; 
    char* str; 
    char temp[2], buffer[20];

    fd = open(arcv[1], O_WRONLY | O_CREAT, 0664);

    printf("Insert number of questions\n");
    scanf("%s", str);

    write(fd, str, sizeof(str));
    write(fd, "\n", 1);
    quest_num = atoi(str);

    for (i = 1; i <= quest_num; i++) 
        printf("Insert question %d\n", i);
        scanf("%[^\n]s", buffer);
        printf("\n %s \n", buffer);
        write(fd, "Question ", );
        sprintf(temp, "%d", i);
        write(fd, temp, sizeof(temp));
        write(fd, "\n", 1);
        write(fd, str, sizeof(temp));
        write(fd, "\n", 1);
    

    close(fd);

我想这样输入:

Insert Number of Question:
 
2
 
Insert Question 1:

X+1=0 x=?

Insert Question 2:
 
X+y=0

在文件内容中我希望它看起来像这样:

Question 1: X+1=0 x=?
1. 5
2. 2
3. 0
4. 1 Question 2: X+y=0
1. X=y
2. X= y
3. X=1
4. Y=1

但我在终端得到了这个:

Insert number of questions

2
 
Insert question 1

x+y x=?

Insert question 2 (input is ignored here)

在文件里面:

2
 
Question 1

x+

Question 2

x=
 
Question 3

2

总而言之,scanf 忽略了空格输入,文件内容中有一个额外的循环。

【问题讨论】:

为什么%[^\n]后面有s?那永远不会匹配任何东西。 @Barmar 我试过 %[^\n]s、%[^\n] 和 %s。它们都不起作用 您从未为str 分配任何内存,因此您会导致scanf("%s", str); 出现未定义的行为。 sizeof(str) 是指针的大小,而不是输入的字符数。使用strlen() 获取字符串的长度。 使用scanf("%s") 后,输入缓冲区留在换行符处。下一个 scanf("%[^\n]s", buffer); 将立即停止,因为没有非换行符。 【参考方案1】:

基本问题是,当您扫描与换行符(%s%[^\n])不匹配的内容时,它不会读取行尾的换行符并将其留给下一个 stdio输入例程读取。您需要以某种方式实际读取并丢弃这些换行符。

最简单的方法是使用fgets 代替scanf 来读取输入行。

    printf("Insert number of questions\n");
    fgets(buffer, sizeof(buffer), stdin);

    write(fd, buffer, strlen(buffer));
    quest_num = atoi(buffer);

    for (i = 1; i <= quest_num; i++) 
        printf("Insert question %d\n", i);
        fgets(buffer, sizeof(buffer), stdin);

请注意,fgets 将读取行包括换行符,并且换行符将在缓冲区中,因此如果您不想要它,则需要将其显式删除.

如果您确实必须使用 scanf,您可以在格式中使用空格来显式跳过前导空格(包括任何延迟的换行符),这实际上可能是可取的。

    printf("Insert number of questions\n");
    scanf("%19s", buffer);

    write(fd, str, strlen(buffer));
    write(fd, "\n", 1);
    quest_num = atoi(buffer);

    for (i = 1; i <= quest_num; i++) 
        printf("Insert question %d\n", i);
        scanf("% 19[^\n]", buffer);
        printf("\n %s \n", buffer);

请注意,当使用带有 %s%[ 和固定大小缓冲区的 scanf 时,您应该在格式中使用明确的大小以避免缓冲区溢出

【讨论】:

以上是关于Unix C 文件,scanf 忽略空格的主要内容,如果未能解决你的问题,请参考以下文章

c语言中怎样用scanf()读入带空格的字符串

为啥不能用scanf读入一个含有空格的字符串

C语言 一行数据 空格分隔

依旧是输入输出(存字符矩阵,空格,换行)

C语言用如何用scanf输入带有空格的字符串

〔杂谈〕关于scanf方法输入字符类型需要加空格问题分析