Как ограничить ввод scanf целыми числами и числами с плавающей запятой (числа в целом) - PullRequest
0 голосов
/ 11 декабря 2018

В настоящее время я учусь программированию на C в университете, и у меня есть задача написать программу, которая выделяет точки перехвата с осью 0 / x любой функции ax ^ 2 + bx + c.

Чтобы убедиться в правильности ввода (int, float и т. Д.), Я запускаю следующий цикл while.До этого а определяется как двойной.

printf("Input for a=");

while (scanf("%lf", &a) == 0)
{
    fflush(stdin);
    scanf("%lf", &a);
    printf("Incorrect Input! New Input needed.\n"); 
    printf("a=");
}

Мне известно, что оператор fflush (stdin) очищает буфер только тогда, когда происходит вторая функция ввода, и поэтому fflush внутри цикла не очищает буфер, и поэтому состояние цикла всегдаправда, и поэтому я создал бесконечный цикл.

Мой проф также запрещает использование goto, поэтому я здесь, потому что я не могу найти разумное решение, которое решает эту проблему.Я также попытался и потерпел неудачу с:

do
{
    printf("\nInput for a= ");
    scanf("%lf", &a);
}

while (isdigit(a));
{
    printf("Thank you.\n");
}

При таком расположении я получаю уведомление об ошибке: Выражение c> = -1 && <= 255. Я думаю, это связано с определением ложной переменной (двойная, цифра) или такой.</p>

Однако мой первоначальный вопрос был более элегантным, есть элегантное решение этой проблемы или, в лучшем случае, любое решение.Спасибо заранее.

1 Ответ

0 голосов
/ 11 декабря 2018

Лукас, я все еще не уверен на 100%, а вы:

"Я спрашиваю, как отличить все числа от всех возможных вводов для scanf."

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

Тем не менее я думаю, что понимаю, что вы спрашиваете, и могу ответитьfflush и чтение значений вопросов.

Для начала, при использовании scanf вы должны проверить возврат и обработать три случая.(1) EOF, пользователь отменяет ввод с помощью Ctrl + d (или Ctrl + z в окнах);(2) происходит сбой совпадения или входа , в результате которого возвращается меньше числа используемых спецификаторов преобразования ;и, наконец, (3) хороший входной случай (когда вы накладываете любые дополнительные проверки, например положительные, менее 100 и т. д.)

Хотя fflush(stdin) является неопределенным поведением в большинстве систем, существуетЕсть ряд реализаций, которые позволяют это.(в первую очередь Windows, но Linux допускает это для поиска потока, например, файла, перенаправленного на stdin). В итоге, он не переносим без предостережений, поэтому лучше предоставить простой эквивалент с getchar()Например,

void empty_stdin (void)
{
    int c = getchar();

    while (c != '\n' && c != EOF)
        c = getchar();
}

Что касается scanf, как я уже упоминал в комментарии, гораздо проще заключить вызов scanf в бесконечный цикл, который вы прерываете, только когда вход удовлетворяет всем вашим ограничениям.,Простым примером, требующим целочисленного ввода, будет:

int getint (int *value, const char *prompt)
{
    /* loop continually until good input or canceled */
    for (;;) {
        int rtn;
        fputs (prompt, stdout);     /* display prompt */
        rtn = scanf ("%d", value);

        if (rtn == EOF) {   /* user generated manual EOF */
            fputs ("<user canceled input>\n", stderr);
            return 0;
        }
        empty_stdin();  /* all other cases - empty input buffer */
        if (rtn == 1)   /* good input, break */
            break;
        /* otherwise matching failure */
        fputs ("  error: invalid integer input.\n", stderr);
    }
    return *value;  /* value also availale through pointer */
}

Если поместить его в простой пример, вы получите:

#include <stdio.h>

void empty_stdin (void)
{
    int c = getchar();

    while (c != '\n' && c != EOF)
        c = getchar();
}

int getint (int *value, const char *prompt)
{
    /* loop continually until good input or canceled */
    for (;;) {
        int rtn;
        fputs (prompt, stdout);     /* display prompt */
        rtn = scanf ("%d", value);

        if (rtn == EOF) {   /* user generated manual EOF */
            fputs ("<user canceled input>\n", stderr);
            return 0;
        }
        empty_stdin();  /* all other cases - empty input buffer */
        if (rtn == 1)   /* good input, break */
            break;
        /* otherwise matching failure */
        fputs ("  error: invalid integer input.\n", stderr);
    }
    return *value;  /* value also availale through pointer */
}

int main (void) {

    int v,
        i = getint (&v, "enter integer value: ");

    if (i)
        printf ("\ninteger: %d\n", v);

    return 0;
}

Пример использования / Вывод

Теперь вы можете сделать все возможное, чтобы нарушить любую входную подпрограмму, которую вы пишете.Если вы обнаружите проблему, исправьте ее и попробуйте снова ее устранить.

Приведенный выше код допускает достаточно надежный ввод значений любого типа, например,

$ ./bin/scanfint
enter integer value: no
  error: invalid integer input.
enter integer value: apples, banannas, and pears
  error: invalid integer input.
enter integer value: 21

integer: 21

Посмотрите вещии дайте мне знать, если ваш вопрос немного отличается или у вас есть дополнительные вопросы по поводу ответа.

...