处理 scanf 和 printf 中的空格

Dealing with whitespace in scanf and printf

提问人:Hack-R 提问时间:5/5/2015 更新时间:5/5/2015 访问量:147

问:

我正在尝试提出一个 C 程序,它可以接受空格,例如名字和姓氏,作为我正在阅读的自学文本的一部分。scanfprintf

我很清楚这些基本/旧函数的缓冲区溢出潜力和此类安全问题,但这完全是出于学习目的,所以我确实需要坚持使用它们。

我的程序如下所示:

#include <stdio.h>
#include <conio.h>

int main(void)
{
    char name[30];

    printf("Type your name\n");

    scanf("%10[0-9a-zA-Z]", name);

    printf("%s\n", name);
    return 0;
}

编译后能够读取带有空格的字符串,但我只能打印第一块文本:

C:\Users\hackr>g++ -o whitespace.exe whitespace.c

C:\Users\hackr>whitespace.exe
Type your name
John Doe
John

C:\Users\hackr>
c

评论


答:

2赞 Patrick Roberts 5/5/2015 #1
scanf("%29[0-9a-zA-Z ]", name);
                    ^

您忘记在正则表达式中为接受的字符添加空格。此外,如果缓冲区为 30 个字节,则应接受 29 个字符,而不是 10 个字符。为 NUL 字符留出空间。

另一件需要注意的事情是,下次您从 读取时,它将读取该行中不在前 29 个字符内的字符,然后开始读取下一个提示的输入。为了解决这个问题,请在以下命令之后添加以下内容:stdinscanfscanf

while (getchar() != '\n')
    ; // read input to end of line

这将始终有效,因为它不在正则表达式的可接受字符中,因此它将保留在缓冲区中。'\n'stdin

1赞 Arun A S 5/5/2015 #2

试试这个

scanf("%29[^\n]", name);

这将一直读取,直到遇到换行符。

评论

0赞 Hack-R 5/5/2015
这也行得通!这可能是一种更好的方法,因为它更简单。谢谢
0赞 chux - Reinstate Monica 5/5/2015
scanf("%[^\n]", name);将不扫描任何内容,如果第一个键为 <Enter>,则将其保留为未初始化状态。name
0赞 Hack-R 5/5/2015
我将不得不在 2 个解决方案中的哪一个上掷硬币标记为被接受,因为它们都是非常好的答案,而且它们是同时编写的。
0赞 Patrick Roberts 5/5/2015
@Hack-R 如果您更愿意使用此选项,请使用此选项,这样就可以避免缓冲区溢出。scanf("%29[^\n]", name);
0赞 Arun A S 5/5/2015
@PatrickRoberts,是的,不知道为什么我以前没有想到这一点。谢谢