2010-04-27 36 views
2

我有一个奇怪的问题如何阅读与空间

我试图读取从控制台一个字符串scanf()的scanf函数

这样

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

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

我想它在gcc编译

+1

我看到你没有把我的建议在你的其他问题(http://stackoverflow.com/questions/2718595/how-to-read-a-string-from-an-delimited-file)关于完全避免'scanf'?叹。 – jamesdlin 2010-04-27 09:20:32

回答

5

尝试使用scanf读取与空格的字符串可以带来缓冲区溢出和杂散换行符停留在输入缓冲器的不必要的问题稍后阅读。 gets()经常建议作为解决这一点,但是,

从手册页:

不要使用gets()函数。因为它是 不可能告诉不知道提前多少字符 如何得到(在 数据)的读出,而且由于得到() 将继续存储字符过去 缓冲区的结束,这是非常 危险使用。它已经被用于破解计算机安全的 。改为使用fgets() 。

因此,而不是使用gets,使用fgets与STDIN流从键盘

1

这应该做工精细阅读字符串,所以别的东西是怎么了。正如霍布​​斯所建议的那样,您可能会在输入中添加一个换行符,在这种情况下,这不会匹配任何内容。它也不会消耗一个换行符,所以如果你在循环中这样做,第一个调用将会到达换行符,然后下一个调用将不会得到任何结果。如果您想阅读换行符,则需要另一个调用,或者在格式字符串中使用空格来跳过空格。检查scanf的返回值以查看它是否实际匹配任何格式说明符也是一个好主意。

另外,您可能需要指定最大长度以避免溢出缓冲区。所以,你想是这样的:

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

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

0

我敢打赌你的scanf电话是在一个循环内。我敢打赌它在你第一次打电话时有效。我敢打赌它只是在第二次和以后的时间才会失败。

第一次,它会读取,直到它到达一个换行符。换行符将保持未读。 (很可能是库在内部读取它并调用ungetc来读取它,但这并不重要,因为从程序的角度来看,换行符是未读的。)

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

第三次...相同。

你可能想这样的:

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

编辑:我不小心复制并粘贴从另一个答案,而不是从问题,插入%* C按预期之前。如果输入的行长度超过100个字节,这种结果行代码会表现得很奇怪,因为%* c会占用一个普通字节而不是换行符。

但是,请注意这将是多么危险的做到这一点:

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

因为在那里,如果你有一个线路输入的比你的缓冲时间越长,投入将走在你的其他变量和堆栈和一切。这称为缓冲区溢出(即使溢出进入堆栈)。

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