Оставив переключатель в то время как (1) - PullRequest
2 голосов
/ 01 апреля 2019

Мне нужен переключатель в то время как.Каждый случай в переключателе является частью меню, которое что-то делает.Также мне нужно обработать все входы от коммутатора, поэтому выбор по умолчанию не является хорошим выбором для меня.Мне нужно полностью уйти, когда пользователь нажимает CTRL + Z в CMD, где происходит программа, чтобы освободить память и выйти из программы.Этот код является только упрощенной версией моей.Не могли бы вы мне помочь?Это последнее, что мне нужно сделать, чтобы завершить задачу.Спасибо.

while (1) {
    scanf("%c", &choose);

    switch (choose) {

    case 1:
        //something
        break;
    case 2:
        // something
        break;

    // no default!

    }
}

Ответы [ 5 ]

4 голосов
/ 02 апреля 2019

Если пользователь нажимает Ctrl + Z в Windows, ваша программа увидит это как конец входного файла (stdin). Когда scanf пытается прочитать байт из stdin, он потерпит неудачу и вернет -1 (EOF), в то время как обычное возвращаемое значение равно 1 (т.е. количество прочитанных элементов).

Таким образом, вы можете использовать следующий код:

while (scanf("%c", &choose) == 1)
{
    switch (choose) {

    case 1:
        //something
        break;
    case 2:
        // something
        break;

    // no default!

    }
}

Я поместил возвращаемое значение scanf в состояние while. Когда scanf больше не может прочитать байт из stdin, цикл прекращается.

4 голосов
/ 02 апреля 2019

Ваша проблема в обработке control-Z не в том, чтобы оставить оператор switch, а в том, что он while.

В системе Windows, когда пользователь нажимает control-Z в начале строки ввода, программное обеспечение будет действовать аналогично концу файла. Примечательно, что при выполнении scanf("%c", &choose); не будет входных данных для чтения, поэтому в choose ничего не будет сохранено. Вместо этого scanf вернет EOF, чтобы указать, что не может быть достигнуто совпадение с "%c" (поскольку данные не были доступны). Однако ваш код не проверяет возвращаемое значение scanf, поэтому он не увидит этого. Один из способов исправить это:

while (1)
{
    int n = scanf("%c", choose);
    if (n != 1) // Did scanf match %c and store something in choose?
        break; // No, so break out of the while loop.
    switch (choose)
    …
}

Тогда возникает вопрос о том, что должно быть в выражении switch. Вы говорите, что вам «необходимо обработать все входы от коммутатора». A char обычно имеет 256 возможных значений. Таким образом, если в switch нет 256 case меток, вы не обрабатываете все входные данные в операторе switch. У вас должен быть ярлык default.

Если в любом из случаев внутри switch необходимо, чтобы выполнение покинуло оператор while, вы можете организовать это различными способами. Одним из способов является использование переменной, чтобы указать, что:

while (1)
{
    int n = scanf("%c", choose);
    if (n != 1) // Did scanf match %c and store something in choose?
        break; // No, so break out of the while loop.

    int LeaveWhile = 0;
    switch (choose)
    {
        case 'A':
            // Code to handle A input.
            break;
        case 'B':
            …
        case something:  // Some case where we want to end the loop.
            LeaveWhile = 1; // Indicate end of loop.
            break;
        …
        default:
            // Code to handle remaining values.
            break;
    }

    // If it is time to leave the while loop, break out of it.
    if (LeaveWhile)
        break;
}
1 голос
/ 02 апреля 2019

Прежде чем описать, как бы я справился с проблемой чрезмерного использования ключевого слова "break" в C, стоит упомянуть еще одну проблему.

Поведение control-C и control-Z зависит от операционной системы и настроек TTY (консоли).

Linux с настройками TTY по умолчанию вызовет прерывание с control-C , что, если не обработано, завершит программу. control-Z приостановит программу. По умолчанию ни в том, ни в другом случае символ не доставляется в программу, и поэтому он не может быть прочитан scanf и не будет передаваться оператором switch.

Windows также прервет работу с control-C по умолчанию.

Я упоминаю об этом, потому что вы зависите от чтения управляющих символов при разборе ввода. Если у вас нет нужного поведения, рассмотрите настройки TTY.

Что касается выхода из «while (1)» изнутри коммутатора, стандартным способом является изменение цикла с «while (1) {}» на «int looping = 1; while (looping) {}", и установите цикл равным 0 внутри тела цикла while.

В некоторых случаях я сделаю это с (прикрыв глаза детей, наблюдающих) переходом к ярлыку через некоторое время. Я заметно отображаю метку goto и делаю отступ в отступе от уровня тела цикла while.

Иногда условия разрыва более естественны, а иногда goto более ясен. Если у вас нет эстетического предпочтения одного над другим, вы можете по умолчанию использовать условие прерывания, а не переходить к следующему.

0 голосов
/ 02 апреля 2019

у вас также есть *do - while* петля.

bool continueLoop = true;

do
{
    switch(something)
    {
        case smth1:
            /* ... */
            break
        case smth2:
            /* ... */
            continueLoop = false;   //whis will exit the loop
            break;
        default
            /* ... */
             break;
    }
}while(continueLoop)
0 голосов
/ 01 апреля 2019

Добавьте флаг в верхней части цикла, который устанавливается, когда вы хотите выйти, затем сделайте это после switch:

while (1) {
    int breakout = 0;

    scanf("%c", &choose);
    switch (choose) {
    case 1:
        //something
        break;
    case 2:
        // something else
        // exit the loop in this case
        breakout = 1;
        break;
    }
    if (breakout) break;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...