getchar () на самом деле не принимает ввод от пользователя - PullRequest
0 голосов
/ 05 марта 2012

Я пишу гибкий генератор командной строки (но не надолго!) В C ++. Я только что закончил писать половину пользовательского ввода. Однако в самой последней команде ввод «проскальзывает», и в getchar () автоматически вводится символ новой строки. Я принял меры предосторожности, чтобы гарантировать, что это не какой-либо переполнение, а именно, очистка как стандартного ввода, так и, по большей части, стандартного вывода. Проблема сохраняется. Вот мой код:

#include <stdio.h>
#include <stdlib.h>

int main () {
    unsigned  long seed = 0, x = 0, y = 0, initial = 0, range = 0;
    int smooth = 0, fail = 1;
    char flagchar1 = 'n';
    printf("Welcome to my diamond-square generator! This isn't full-feature yet, so I'm just gonna have you input the variables one by one. ");
    do {
        printf("Please input the seed (this is a positive integer):\n");
        fail = scanf("%lu", &seed);
        while (fail == 0) {
            printf("Try again, smartass.\n");
            fail = scanf("%lu", &seed);
        }
        fail = 1;
        printf("Now input the x, or horizontal, size of your grid:\n");
        fail = scanf("%lu", &x);
        while (fail == 0) {
            printf("An integer. Not a string. An integer. You can do that, can't you?\n");
            fail = scanf("%lu", &x);
        }
        fail = 1;
        printf("Now input the y, or vertical, size of your grid:\n");
        fail = scanf("%lu", &y);
        while (fail == 0) {
            printf("What was that supposed to be? An integer, please.\n");
            fail = scanf("%lu", &y);
        }
        fail = 1;
        printf("Now input about how high you'd like the grid to be (this goes from a scale of 1 to 256):\n");
        fail = scanf("%lu", &initial);
        while (initial == 0 || initial > 256 || fail == 0) {
            printf("ahahahahaha how HIGH do you have to be just to HAVE that hieght........\n");
            fail = scanf("%lu", &initial);
        }
        fail = 1;
        printf("Now input the range of the heights on your grid (this must be equal to or less than 256):\n");
        scanf("%lu", &range);
        while (range >= 256 || fail == 0) {
            printf("What did I say about being equal to or less than 256? Give me something reasonable to work with here.\n");
            fail = scanf("%lu", &range);
        }
        fail = 1;
        printf("Just one more variable to go! Now, I need you to input the smoothness of your grid. Smaller numbers make spikier grids. You can make this negative, but beware!\n");
        fail = scanf("%d", &smooth);
        while (fail == 0) {
            printf("That... was not a number.\n");
            fail = scanf("%d", &smooth);
        }
        fail = 1;
        printf("\nOkay. Are these the values you want?\n   Seed:       %lu\n   Width:      %lu\n   Length:     %lu\n   Height:     %lu\n   Range:      %lu\n   Smoothness: %d\nDo you want to keep these? Type Y/n.\n", seed, x, y, initial, range, smooth);
        fflush(stdin);
        fflush(stdout);
        flagchar1 = getchar();
    } while (flagchar1 != 'y' && flagchar1 != 'Y' && flagchar1 != '\n');
}

Вот мой вывод, программа закончилась (программа просто повторяет весь цикл выполнения, если я удаляю && flagchar1 != '\n' из while()):

    Welcome to my diamond-square generator! This isn't full-feature yet, so I'm just gonna have you input the variables one by one. Please input the seed (this is a positive integer):
    12345678
    Now input the x, or horizontal, size of your grid:
    40
    Now input the y, or vertical, size of your grid:
    30
    Now input about how high you'd like the grid to be (this goes from a scale of 1 to 256):
    1288
    ahahahahaha how HIGH do you have to be just to HAVE that hieght........
    128
    Now input the range of the heights on your grid (this must be equal to or less than 256):
    30
    Just one more variable to go! Now, I need you to input the smoothness of your grid. Smaller numbers make spikier grids. You can make this negative, but beware!
    10

Okay. Are these the values you want?
  Seed:       12345678
  Width:      40
  Length:     30
  Height:     128
  Range:      30
  Smoothness: 10
Do you want to keep these? Type Y/n.

Что происходит, и как мне это исправить?

P.S. Я знаю, что моя проверка ввода по существу бесполезна. Помощь с этим также высоко ценится.

Ответы [ 5 ]

2 голосов
/ 05 марта 2012

Сделайте так, чтобы конец вашего цикла выглядел так:

    // Ignore remaining characters on current line.
    int ch;
    while( (ch = getchar()) != EOF && ch != '\n')
      ;
    // fetch first character on next line
    flagchar1 = getchar();
} while (flagchar1 != 'y' && flagchar1 != 'Y' && flagchar1 != '\n');

Вы оставляете '\n' в stdin после вашего последнего звонка на scanf.

Вы не должны полагаться на fflush(stdin), имеющую какое-либо конкретное поведение. Результат вызова fflush для входного потока не определен. См. Использование fflush (stdin)

0 голосов
/ 06 марта 2012

Предложения:

  1. Использовать потоки C ++.
  2. Используйте tolower или toupper перед сравнением символов.
  3. Использовать std::string.

Язык C, который использует fgets, gets, fflush, strcmp,, имеет много проблем в этой области. Язык C ++ решил многие из этих проблем в классах std::stream.

Поскольку вы не используете функции C ++, вы должны изменить тег C ++ на C .

0 голосов
/ 06 марта 2012

Полагаю, вы работаете в Linux? Это отлично работает на VS в Windows. Он запрашивает, читает с клавиатуры и, если проверено, содержит правильные «y» или «Y» в вопросе.

Я мог бы предложить вам изменить последнее сканирование на:

fail = scanf("%d ", &smooth);

Вы также можете попробовать вызвать fpurge () вместо fflush (), но это нестандартно, и я думаю, что пробел в конце строки формата даст вам то, что вы хотите.

Конечный пробел попросит scanf использовать любые дополнительные пробелы (включая переводы строк) во входных данных. fflush (), вероятно, не будет делать то, что вы хотите для ввода.

Я подозреваю, что любая система, в которой вы находитесь, действительно оставляет возврат каретки в потоке, и если вы напечатаете flagchar1 как int, вы получите 10?

0 голосов
/ 05 марта 2012

Попробуйте

} while (flagchar1! = 'Y' || flagchar1! = 'Y' || flagchar1! = '\ N');

вместо

} while (flagchar1! = 'Y' && flagchar1! = 'Y' && flagchar1! = '\ N');

0 голосов
/ 05 марта 2012

Код ведет себя именно так, как вы говорите.Если пользователь вводит «y», «Y» или вводит, одно из этих условий в цикле while будет ложным, что приведет к его выходу.

То, что вы хотите:

while (flagchar1 == 'y' || flagchar1 == 'Y' || flagchar1 == '\n');

Редактировать: я бы также удалил fflush (stdin) и заменил getchar () на fgets ().Это гарантирует, что вся строка будет прочитана без использования fflush, что может быть проблемой.

...