我遇到了一个奇怪的问题
我正在尝试使用scanf()
从控制台读取字符串 像这样scanf("%[^\n]",string1);
但它没有读任何东西。它只是跳过整个scanf。
我在gcc编译器中尝试它
答案 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;
}