Как я могу использовать функцию «Get» много раз в моей программе C? - PullRequest
0 голосов
/ 17 апреля 2020

Мой код:

#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)

Ответы [ 2 ]

3 голосов
/ 17 апреля 2020

Самое важное для вас сообщение:

Никогда не используйте gets - оно не может защитить от переполнения буфера. Ваш буфер может содержать 9 символов и символ завершения, но gets позволит пользователю вводить больше символов и тем самым перезаписывать другие части памяти программ. Злоумышленники могут использовать это. Так что нет gets в любой программе.

Вместо этого используйте fgets!

Тем не менее, что для вас не так?

scanf оставляет новую строку ( aka a '\n') во входном потоке. Поэтому первый gets просто читает пустую строку. А второй gets затем читает «сурья».

Проверьте это так:

#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 содержит слово «сурья» (длина 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 голосов
/ 17 апреля 2020

Как я могу многократно использовать функцию «get» в программе C?

Вы должны никогда использовать gets() в своей программе. Это устарело, потому что это опасно из-за переполнения буфера, поскольку у него нет возможности прекратить потребление при заданном c количестве символов - например, и, что особенно важно, - количестве символов в буфере, a или b с каждым 10 символов, способен удерживать.

Также объясняется здесь:

Почему функция get так опасна, что ее не следует использовать?

Специально, в this ответ Джонатана Леффлера.

Используйте вместо него fgets().


Также определение a и b внутри while l oop Это не имеет никакого смысла, даже если это просто игрушечная программа и для целей обучения.

Кроме того, обратите внимание, что 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...