如何在我的C程序中多次使用“ gets”功能?

问题描述 投票:0回答:2

我的代码:

#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)
c memory runtime-error runtime gets
2个回答
3
投票

对您来说最重要的信息是:

从不使用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'


2
投票

如何在C程序中多次使用“ gets”功能?

您应该从不在程序中使用gets()。不建议使用它,因为存在导致缓冲区溢出的危险,因为它不可能停止消耗特定数量的字符-例如最重要的是-缓冲区可以容纳的字符数ab(每10个字符)。

也在这里解释:

Why is the gets function so dangerous that it should not be used?

特别是在this中,乔纳森·莱夫勒的回答。

改为使用fgets()


而且a循环中bwhile的定义也没有任何意义,即使艰难,这只是一个玩具程序,也是出于学习目的。

[此外,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
© www.soinside.com 2019 - 2024. All rights reserved.