我的代码:
#include <stdio.h>
#include <math.h>
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
char a[10],b[10];
puts("enter");
gets(a);
puts("enter");
gets(b);
puts("enter");
puts(a);
puts(b);
}
return 0;
}
输出:
1
enter
enter
surya (string entered by user)
enter
surya (last puts function worked)
对您来说最重要的信息是:
从不使用gets
-它无法防止缓冲区溢出。您的缓冲区可以容纳9个字符和终止字符,但是gets
允许用户键入更多字符,从而覆盖程序存储器的其他部分。攻击者可以利用这一点。因此,任何程序中都没有gets
。
改为使用fgets
!
那是-你怎么了?
scanf
在输入流中留下换行符(又名'\n'
)。因此,第一个gets
只是读取一个空字符串。然后第二个gets
读为“ surya”。
像这样测试:
#include <stdio.h>
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
char a[10],b[10];
puts("enter");
gets(a); // !!! Use fgets instead
puts("enter");
gets(b); // !!! Use fgets instead
puts("enter");
printf("|%s| %zu", a, strlen(a));
printf("|%s| %zu", b, strlen(b));
}
return 0;
}
输入:
1
surya
whatever
输出:
enter
enter
enter
|| 0|surya| 5
因此,您在这里看到a
只是一个空字符串(长度为零),b
包含单词“ surya”(长度为5)。
如果使用fgets
,则可以防止用户启动的缓冲区溢出,这很重要。
但是fgets
将不是删除'\n'
中剩余的scanf
。您仍然必须摆脱自我。
为此,我建议也删除scanf
。使用fgets
,然后使用sscanf
。喜欢:
if (fgets(a,sizeof a, stdin) == NULL)
{
// Error
exit(1);
}
if (sscanf(a, "%d", &t) != 1)
{
// Error
exit(1);
}
因此,当输入'\n'
时,以上代码将自动从输入流中删除t
,随后的fgets
将以下一个单词开头。
全部放在一起:
#include <stdio.h>
int main()
{
int t;
char a[10],b[10];
if (fgets(a,sizeof a, stdin) == NULL)
{
// Error
exit(1);
}
if (sscanf(a, "%d", &t) != 1)
{
// Error
exit(1);
}
while(t--)
{
puts("enter");
if (fgets(a,sizeof a, stdin) == NULL)
{
// Error
exit(1);
}
puts("enter");
if (fgets(b,sizeof b, stdin) == NULL)
{
// Error
exit(1);
}
puts("enter");
printf("%s", a);
printf("%s", b);
}
return 0;
}
输入:
1
surya
whatever
输出:
enter
enter
enter
surya
whatever
最后注:
fgets
将-与gets
不同-还将'\n'
保存到目标缓冲区。根据您要执行的操作,您可能必须从缓冲区中删除该'\n'
。
如何在C程序中多次使用“ gets”功能?
您应该从不在程序中使用gets()
。不建议使用它,因为存在导致缓冲区溢出的危险,因为它不可能停止消耗特定数量的字符-例如最重要的是-缓冲区可以容纳的字符数a
或b
(每10个字符)。
也在这里解释:
Why is the gets function so dangerous that it should not be used?
特别是在this中,乔纳森·莱夫勒的回答。
改为使用fgets()
。
而且a
循环中b
和while
的定义也没有任何意义,即使艰难,这只是一个玩具程序,也是出于学习目的。
[此外,scanf()
保留换行符,按此键可从scanf()
中的stdin
调用返回。您必须抓住这个字符,否则此后的第一个fgets()
将占用此字符。
这里是更正的程序:
#include <stdio.h>
int main()
{
int t;
char a[10],b[10];
if(scanf("%d",&t) != 1)
{
printf("Error at scanning!");
return 1;
}
getchar(); // For catching the left newline from scanf().
while(t--)
{
puts("Enter string A: ");
fgets(a,sizeof a, stdin);
puts("Enter string B: ");
fgets(b,sizeof b, stdin);
printf("\n");
puts(a);
puts(b);
printf("\n\n");
}
return 0;
}
执行:
$PATH/a.out
2
Enter string A:
hello
Enter string B:
world
hello
world
Enter string A:
apple
Enter string B:
banana
apple
banana