如何用空格读取scanf

我有一个奇怪的问题

我正在尝试使用scanf()从控制台读取字符串

像这样

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

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

我在gcc编译器中尝试它

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

从联机帮助页:

永远不要使用gets()。 因为如果事先不知道数据就不可能分辨出get()会读取多少个字符,并且因为gets()将继续存储超过缓冲区末尾的字符,所以使用它是非常危险的。 它已被用来打破计算机安全。 请改用fgets()。

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

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

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

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

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

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

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

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

第三次……同样的。

你可能想要这个:

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

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

但是,请注意这样做会有多危险:

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

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

 #include  #include  #include  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; }