如何在我的 C 程序中多次使用 "gets" 函数?
How can I use the "gets" function many times in my C program?
我的代码:
#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)
How can I use “gets” function many times in C program?
你应该永远不要在你的程序中使用gets()
。它已被弃用,因为它很可能导致缓冲区溢出,因为它不可能停止使用特定数量的字符 - f.e。最重要的是 - 缓冲区能够容纳的字符数量,a
或 b
每 10 个字符。
这里也有说明:
Why is the gets function so dangerous that it should not be used?
特别是在乔纳森·莱弗勒的 this 回答中。
改用fgets()
。
此外,while
循环中 a
和 b
的定义没有任何意义,尽管这只是一个玩具程序,仅供学习之用。
另外请注意,scanf()
留下了换行符,由 stdin
中的 scanf()
调用按到 return 生成。你必须抓住这个,否则之后的第一个 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
对您来说最重要的信息是:
永远不要使用 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
不会 删除 scanf
遗留下来的 '\n'
。你仍然需要自己摆脱它。
为此,我建议也删除 scanf
。使用 fgets
,然后使用 sscanf
。喜欢:
if (fgets(a,sizeof a, stdin) == NULL)
{
// Error
exit(1);
}
if (sscanf(a, "%d", &t) != 1)
{
// Error
exit(1);
}
所以上面的代码会在输入t
时自动从输入流中移除'\n'
,随后的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'
。
我的代码:
#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)
How can I use “gets” function many times in C program?
你应该永远不要在你的程序中使用gets()
。它已被弃用,因为它很可能导致缓冲区溢出,因为它不可能停止使用特定数量的字符 - f.e。最重要的是 - 缓冲区能够容纳的字符数量,a
或 b
每 10 个字符。
这里也有说明:
Why is the gets function so dangerous that it should not be used?
特别是在乔纳森·莱弗勒的 this 回答中。
改用fgets()
。
此外,while
循环中 a
和 b
的定义没有任何意义,尽管这只是一个玩具程序,仅供学习之用。
另外请注意,scanf()
留下了换行符,由 stdin
中的 scanf()
调用按到 return 生成。你必须抓住这个,否则之后的第一个 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
对您来说最重要的信息是:
永远不要使用 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
不会 删除 scanf
遗留下来的 '\n'
。你仍然需要自己摆脱它。
为此,我建议也删除 scanf
。使用 fgets
,然后使用 sscanf
。喜欢:
if (fgets(a,sizeof a, stdin) == NULL)
{
// Error
exit(1);
}
if (sscanf(a, "%d", &t) != 1)
{
// Error
exit(1);
}
所以上面的代码会在输入t
时自动从输入流中移除'\n'
,随后的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'
。