Ввод символа, кроме цифр, заставит мою программу выводить бесконечно. Как это исправить?

Когда я ввожу какие-либо символы, кроме цифр, в «Введите свой выбор», он будет бесконечно зацикливаться. Например: Ввод символа. Результат Как видите, цикл будет бесконечным, если я не введу число от 1 до 10, представленное для каждого выбора продукта. Или при вводе любого числа, кроме чисел от 1 до 10, это будет распознано как неверный выбор. P.S. Кодер-новичок.

Это код программы.

#include <stdio.h>

int main(void)
{
    int choice, quantity, total = 0, price = 0;
    char end;

    do
    {
        printf("\nWelcome to our store!\n\n");
        printf("Welcome to our store!\n");
        printf("Please select a product from the following list:\n");
        printf("1. Oishi Prawn Crackers - 7 PHP\n");
        printf("2. Piattos - 16 PHP\n");
        printf("3. Coca-Cola - 40 PHP\n");
        printf("4. Sting Energy Drink - 25 PHP\n");
        printf("5. Gatorade - 43 PHP\n");
        printf("6. Nature Spring 500mL - 10 PHP\n");
        printf("7. KitKat - 30 PHP\n");
        printf("8. Snickers - 44 PHP\n");
        printf("9. Oishi Prawn Crackers - 7 PHP\n");
        printf("10. M&M's - 80 PHP\n");
        printf("Enter 0 to finish.\n");
        printf("\nProduct                 Quantity   Price\n");
        printf("----------------------------------------\n");

        do
        {
            printf("Enter your choice: ");
            scanf(" %d", &choice);

            if (choice == 0)
            {
                break;
            }

            printf("Enter the quantity: ");
            scanf(" %d", &quantity);

            switch (choice)
            {
            case 1:
                printf("Oishi Prawn Crackers        %d        %d\n", quantity, price = 7 * quantity);
                total += 7 * quantity;
                break;
            case 2:
                printf("Piattos                     %d        %d\n", quantity, price = 16 * quantity);
                total += 15 * quantity;
                break;
            case 3:
                printf("Coca-Cola                   %d        %d\n", quantity, price = 40 * quantity);
                total += 40 * quantity;
                break;
            case 4:
                printf("Sting Energy Drink          %d        %d\n", quantity, price = 25 * quantity);
                total += 25 * quantity;
                break;
            case 5:
                printf("Gatorade 500mL              %d        %d\n", quantity, price = 43 * quantity);
                total += 43 * quantity;
                break;
            case 6:
                printf("Nature Spring 500mL         %d        %d\n", quantity, price = 10 * quantity);
                total += 10 * quantity;
                break;
            case 7:
                printf("KitKat                      %d        %d\n", quantity, price = 30 * quantity);
                total += 30 * quantity;
                break;
            case 8:
                printf("Snickers                    %d        %d\n", quantity, price = 44 * quantity);
                total += 44 * quantity;
                break;
            case 9:
                printf("M&M's                       %d        %d\n", quantity, price = 40 * quantity);
                total += 40 * quantity;
                break;
            case 10:
                printf("Pringles                    %d        %d\n", quantity, price = 80 * quantity);
                total += 80 * quantity;
                break;
            default:
                printf("Invalid choice.\n");
                break;
            }
        } while (choice != 0);

        printf("----------------------------------------\n");
        printf("Total cost: %d PHP\n", total);
        printf("Thank you for shopping with us!\n");
        printf("\nWant to Buy Again?\n");
        printf("Y if Yes\n");
        printf("Type any key if No\n");
        scanf(" %c", &end);

        switch (end) {
        case 'Y':
            printf("\nOK!\n");
            break;
        default:
            printf("\nBYE!\n");
            break;
        }
    } while (end == 'Y');
    return 0;
}

Итак, я набрал числа от 1 до 10, и кажется, что он распознает каждый продукт и запросит количество. И введя любые числа, он сделает то, что должен, и выведет Invalid Choice. Я попытался изменить переменные, ожидая, что это будет исправлено, но это вообще не сработает. Кажется, я что-то упустил, но не знаю где.

Support Ukraine 10.01.2023 12:02

Добро пожаловать в СО. Ваш первый шаг должен заключаться в обнаружении проблемы. Вы всегда должны проверять возвращаемое значение scanf. Если ввод не соответствует спецификатору формата, символ не используется. Вы должны удалить его из ввода вручную.

Gerhardh 10.01.2023 12:03

Это прозвучит удивительно, но: Мой вам совет: не тратьте время на решение этой проблемы прямо сейчас. Конечно, это реальная проблема, но единственный разумный способ решить ее — вообще не использовать scanf. Но если вы только начинаете, может быть довольно удобно использовать scanf в течение первых нескольких недель, несмотря на его долгосрочную бесполезность. Когда вы будете готовы, вы можете научиться вводить данные, используя другие (и лучшие) методы, чем scanf.

Steve Summit 10.01.2023 14:18
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Калькулятор CGPA 12 для семестра
Калькулятор CGPA 12 для семестра
Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие...
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
О тренинге HTML JavaScript :HTML (язык гипертекстовой разметки) и CSS (каскадные таблицы стилей) - две основные технологии для создания веб-страниц....
Как собрать/развернуть часть вашего приложения Angular
Как собрать/развернуть часть вашего приложения Angular
Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?
Запуск PHP на IIS без использования программы установки веб-платформы
Запуск PHP на IIS без использования программы установки веб-платформы
Установщик веб-платформы, предлагаемый компанией Microsoft, перестанет работать 31 декабря 2022 года. Его закрытие привело к тому, что мы не можем...
Оптимизация React Context шаг за шагом в 4 примерах
Оптимизация React Context шаг за шагом в 4 примерах
При использовании компонентов React в сочетании с Context вы можете оптимизировать рендеринг, обернув ваш компонент React в React.memo сразу после...
2
3
61
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ну вот:

#include <stdio.h>

int main(void)
{
    int choice = 0, quantity, total = 0, price = 0;
    char end;

    do
    {
        printf("\nWelcome to our store!\n\n");
        printf("Welcome to our store!\n");
        printf("Please select a product from the following list:\n");
        printf("1. Oishi Prawn Crackers - 7 PHP\n");
        printf("2. Piattos - 16 PHP\n");
        printf("3. Coca-Cola - 40 PHP\n");
        printf("4. Sting Energy Drink - 25 PHP\n");
        printf("5. Gatorade - 43 PHP\n");
        printf("6. Nature Spring 500mL - 10 PHP\n");
        printf("7. KitKat - 30 PHP\n");
        printf("8. Snickers - 44 PHP\n");
        printf("9. Oishi Prawn Crackers - 7 PHP\n");
        printf("10. M&M's - 80 PHP\n");
        printf("Enter 0 to finish.\n");
        printf("\nProduct                 Quantity   Price\n");
        printf("----------------------------------------\n");

        do
        {
            int choice = 0;
            
            printf("Enter your choice: ");
            scanf(" %d", &choice);
            while ( getchar() != '\n' );
            if (choice == 0 || choice > 10)
            {
                break;
            }

            printf("Enter the quantity: ");
            scanf(" %d", &quantity);

            switch (choice)
            {
            case 1:
                printf("Oishi Prawn Crackers        %d        %d\n", quantity, price = 7 * quantity);
                total += 7 * quantity;
                break;
            case 2:
                printf("Piattos                     %d        %d\n", quantity, price = 16 * quantity);
                total += 15 * quantity;
                break;
            case 3:
                printf("Coca-Cola                   %d        %d\n", quantity, price = 40 * quantity);
                total += 40 * quantity;
                break;
            case 4:
                printf("Sting Energy Drink          %d        %d\n", quantity, price = 25 * quantity);
                total += 25 * quantity;
                break;
            case 5:
                printf("Gatorade 500mL              %d        %d\n", quantity, price = 43 * quantity);
                total += 43 * quantity;
                break;
            case 6:
                printf("Nature Spring 500mL         %d        %d\n", quantity, price = 10 * quantity);
                total += 10 * quantity;
                break;
            case 7:
                printf("KitKat                      %d        %d\n", quantity, price = 30 * quantity);
                total += 30 * quantity;
                break;
            case 8:
                printf("Snickers                    %d        %d\n", quantity, price = 44 * quantity);
                total += 44 * quantity;
                break;
            case 9:
                printf("M&M's                       %d        %d\n", quantity, price = 40 * quantity);
                total += 40 * quantity;
                break;
            case 10:
                printf("Pringles                    %d        %d\n", quantity, price = 80 * quantity);
                total += 80 * quantity;
                break;
            default:
                printf("Invalid choice.\n");
                break;
            }
        } while (choice != 0);

        printf("----------------------------------------\n");
        printf("Total cost: %d PHP\n", total);
        printf("Thank you for shopping with us!\n");
        printf("\nWant to Buy Again?\n");
        printf("Y if Yes\n");
        printf("Type any key if No\n");
        scanf(" %c", &end);

        switch (end) {
        case 'Y':
            printf("\nOK!\n");
            break;
        default:
            printf("\nBYE!\n");
            break;
        }
    } while (end == 'Y');
    return 0;
}

Угу... В этом коде ДВА* экземпляра scanf()... Вам нужно проделать больше работы... И считается, что "хороший" ответ - это не просто "дамп кода" без объяснения ОП ошибка/проблема.

Fe2O3 10.01.2023 12:20

Неважно, добавление while ( getchar() != '\n' ); вводит возможность другого бесконечного цикла, если EOF будет достигнуто до того, как будет прочитан следующий \n символ.

Andrew Henle 10.01.2023 13:13
Ответ принят как подходящий

Рассмотрите возможность использования структуры для хранения имени и стоимости каждого продукта. Это позволит избежать ошибок в повторениях. scanint и scanchar будут сканировать и отбрасывать ожидающие символы во входном потоке. Дополнительные непробельные символы вызовут повторную подсказку.

#include <stdio.h>

typedef struct item item_t;
struct item {
    char const *name;
    int cost;
};

int scanint ( char const *prompt);
int scanchar ( char const *prompt);
void menu ( size_t items, item_t product[]);

int main(void)
{
    item_t products[] = {
          { "Oishi Prawn Crackers",  7}
        , { "Piattos",              16}
        , { "Coca-Cola",            40}
        , { "Sting Energy Drink",   25}
        , { "Gatorade",             43}
        , { "Nature Spring 500mL",  10}
        , { "KitKat",               30}
        , { "Snickers",             44}
        , { "Pringles",              7}
        , { "M&M's",                80}
    };

    int choice = 0;
    int quantity = 0;
    int total = 0;
    char end = 0;
    size_t items = sizeof products / sizeof *products;

    do {
        printf("\nWelcome to our store!\n\n");
        menu ( items, products);

        while ( 1) {
            choice = scanint ( "Enter your choice: ");

            if (choice == 0) {
                break;
            }
            --choice;

            if ( choice < items) {
                quantity = scanint ( "\tEnter the quantity: ");

                printf ( "%-22s%3d %7d\n"
                , products[choice].name
                , quantity
                , products[choice].cost * quantity);
                total += products[choice].cost * quantity;
            }
            else {
                printf("Invalid choice.\n");
            }
        }

        printf ( "----------------------------------------\n");
        printf ( "Total cost: %d PHP\n", total);
        printf ( "Thank you for shopping with us!\n");

        end = scanchar ( "\nWant to Buy Again?\nY if Yes\nType any key if No\n");

        switch (end) {
        case 'Y':
            printf("\nOK!\n");
            break;
        default:
            printf("\nBYE!\n");
            break;
        }
    } while (end == 'Y');
    return 0;
}

void menu ( size_t items, item_t product[]) {
    printf ( "Please select a product from the following list:\n");
    for ( int each = 0; each < items; ++each) {
        printf ( "%2d. %-22s%3d PHP\n"
        , each + 1, product[each].name, product[each].cost);
    }
}

int scanint ( char const *prompt) {
    char newline[2] = "";
    int extra = 0;
    int scanned = 0;
    int value = 0;

    do {
        printf ( "%s", prompt);
        fflush ( stdout);
        scanned = scanf ( "%d", &value);
        if ( scanned == EOF) {
            return 0;
        }
        extra = 0;
        scanf ( "%*[ \f\t\v]"); // scan and discard whitespace except newline
        scanf ( "%*[^\n]%n", &extra); // scan discard and count not a newline
        scanned += scanf ( "%1[\n]", newline);
    } while ( value < 0 || scanned != 2 || extra != 0);

    return value;
}

int scanchar ( char const *prompt) {
    char newline[2] = "";
    int extra = 0;
    int scanned = 0;
    char value = 0;

    do {
        printf ( "%s", prompt);
        fflush ( stdout);
        scanned = scanf ( " %c", &value);
        if ( scanned == EOF) {
            return 0;
        }
        extra = 0;
        scanf ( "%*[ \f\t\v]"); // scan and discard trailing whitespace except newline
        scanf ( "%*[^\n]%n", &extra); // scan discard and count not a newline
        scanned += scanf ( "%1[\n]", newline);
    } while ( scanned != 2 || extra != 0);

    return value;
}

Другие вопросы по теме