получает () принимать входные данные, фактически не давая ему никакого ввода? - PullRequest
2 голосов
/ 18 сентября 2010

Я довольно новичок в C, так что извините, если это глупый вопрос, но когда я запускаю следующий код:

#include <stdio.h>

int main () {
    int i;
    int test[10];
    char string[81];

    for(i = 0; i < 10; i++){
        scanf("%d", &test[i]);
    }

    for(i=0; i < 7; i++){
        gets(string);
        printf("String was entered\n");
    }

}

и введите любые 10 цифр, строка "строка была введена" будетнапечатано, хотя я не вводил строку в командном окне.Кто-нибудь может объяснить почему?Есть ли способ остановить это?

Спасибо!

Ответы [ 3 ]

4 голосов
/ 18 сентября 2010

После того, как вы прочитали данные, используя scanf, символ новой строки все еще находится в очереди ввода и ожидает чтения. gets читает этот символ новой строки и останавливается (потому что он достиг конца строки!)

Обратите внимание, что плохая идея использовать gets: он не позволяет установить ограничение на количество символов, считываемых в буфер, поэтому, если вы введете больше символов, чем уместится в буфер, вы в конечном итоге переполните буфер, что приведет к повреждению данных, падению приложения, огромной уязвимости безопасности и / или любому количеству других непредсказуемых результатов. Для безопасной альтернативы вы можете использовать fgets вместо stdin:

fgets(string, sizeof(string), stdin);

(Обратите внимание, что вы, вероятно, захотите использовать символическую константу некоторого вида для размера string, чтобы не повторять ее в нескольких местах - или используйте sizeof(string), когда определение массива является видимым. )

3 голосов
/ 18 сентября 2010

По предположению, scanf() не потреблял новую строку, которую вам нужно было набрать, чтобы он мог обработать десять целых чисел, которые вы хотели получить перед строкой.Таким образом, после последнего вызова scanf(), gets() сталкивается с входным буфером, который начинается с новой строки.Presto, он выполнил свою спецификацию, поэтому ничего не копирует в свой буфер и возвращает.

В общем, scanf() и gets() - плохой выбор для нового кода.У них обоих есть проблемы, которые делают их болезненными при правильном использовании или даже опасными при использовании вообще.

В частности, gets() не проверяет и не может проверить размер своего выходного буфера, поэтому он легко перезапишет любую память, расположенную после его буфера.В этом заключается порча глобального состояния или стека.Если это стек, то можно использовать это, чтобы получить контроль над программой и заставить ее выполнять произвольный код.Это не очень хорошая вещь.

Было бы лучше использовать ваш входной поток с fgets(), который имеет ограничение на размер буфера, и анализировать его с sscanf() и другими функциями после прочтения.

0 голосов
/ 14 марта 2015

следующий код должен работать

#include <stdio.h>
 int main () {
 int i;
  int test[10];
 char string[81],s[1];
 for(i = 0; i < 10; i++){
    scanf("%d", &test[i]);
}

gets(s);

for(i=0; i < 7; i++){
    gets(string);
    printf("String was entered\n");
 }

}

массив символов s [1] использовался для перехвата символа новой строки, оставленного необработанным scanf

...