繁体   English   中英

如何用空格读取scanf

[英]how to read scanf with spaces

我有一个奇怪的问题

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

像这样

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

但它什么也没读。 它只是跳过整个scanf。

我正在gcc编译器中尝试

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

从联机帮助页:

永远不要使用gets()。 因为无法不事先知道数据就无法知道将读取多少个字符gets(),并且因为gets()将继续存储超过缓冲区末尾的字符,所以使用它非常危险。 它已被用来破坏计算机的安全性。 使用fgets()代替。

因此,不要使用gets ,而是将fgets与STDIN流一起使用,以从键盘读取字符串

那应该工作正常,所以其他地方出了问题。 正如霍布​​斯所建议的那样,您可能在输入中包含换行符,在这种情况下,这将不匹配任何内容。 它也不会占用换行符,因此,如果您循环执行此操作,则第一个调用将到达换行符,然后下一个调用将什么也没有。 如果要阅读换行符,则需要另一个调用,或者在格式字符串中使用空格来跳过空格。 检查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 <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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM