如何用空格读取scanf

时间:2010-04-27 04:52:58

标签: c gcc

我遇到了一个奇怪的问题

我正在尝试使用scanf()

从控制台读取字符串 像这样

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

但它没有读任何东西。它只是跳过整个scanf。

我在gcc编译器中尝试它

4 个答案:

答案 0 :(得分:5)

尝试使用scanf读取带空格的字符串可能会带来不必要的缓冲区溢出问题,并且滞留在输入缓冲区中的杂散换行符将在以后读取。但是,gets()通常被建议作为解决方案,

从联系手册:

  

永远不要使用gets()。因为它是   在不知道的情况下无法分辨   数据提前有多少个字符   gets()将读取,因为gets()   将继续存储过去的人物   缓冲区的结束,非常   使用危险。它已经习惯了   打破计算机安全。使用fgets()   代替。

因此,不要使用gets,而是使用带有STDIN流的fgets来从键盘读取字符串

答案 1 :(得分:1)

这应该可以正常工作,所以别的东西出错了。正如hobbs建议的那样,你可能在输入上有一个换行符,在这种情况下,这将无法匹配。它也不会消耗换行符,所以如果你在一个循环中执行此操作,第一个调用将转到换行符,然后下一个调用将什么也得不到。如果要读取换行符,则需要另一个调用,或者使用格式字符串中的空格来跳过空格。检查scanf的返回值以查看它是否与任何格式说明符匹配也是一个好主意。

此外,您可能希望指定最大长度以避免溢出缓冲区。所以你需要这样的东西:

char buffer[100];
if (scanf(" %99[^\n]", buffer) == 1) {
    /* read something into buffer */

这将跳过(忽略)一行开头的任何空行和空格,最多可读取99个字符的输入,不包括换行符。不会跳过尾随或嵌入的空格,只会导致空格。

答案 2 :(得分:0)

我敢打赌你的scanf调用是在循环中。我打赌它会在你第一次打电话时起作用。我敢打赌它只会在第二次及以后失败。

第一次,它将一直读到它到达换行符。换行符将保持未读状态。 (可能的情况是库内部会读取它并调用ungetc来解读它,但这没关系,因为从你的程序的角度来看,新行是未读的。)

第二次,它将一直读到它到达换行符。该换行符仍然在行的前面等待,scanf将读取所有等待它的所有0个字符。

第三次......同样的。

你可能想要这个:

if (scanf("%99[^\n]%*c", buffer) == 1) {

编辑:在按预期插入%* c之前,我意外地复制并粘贴了另一个答案,而不是问题。如果您的输入行长度超过100个字节,则生成的代码行会很奇怪,因为%* c将使用普通字节而不是换行符。

然而,请注意这样做会有多危险:

scanf("%[^n]%*c", string1);

因为在那里,如果你的输入行长于你的缓冲区,输入将遍历你的其他变量和堆栈以及所有内容。这称为缓冲区溢出(即使溢出进入堆栈)。

答案 3 :(得分:0)

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

char *text(int n);

int main()
{
char str[10];
printf("enter username : ");
scanf(text(9),str);
printf("username = %s",str);

return 0;
}

char *text(int n)
{
fflush(stdin);fflush(stdout);
char str[50]="%",buf[50],st2[10]="[^\n]s";
char *s;itoa(n,buf,10);
// n == -1 no buffer protection
if(n != -1) strcat(str,buf);
strcat(str,st2);s=strdup(str);
fflush(stdin);fflush(stdout);
return s;
}