Пауза консоли в программе на С++

Какой лучший способ приостановить консоль в программах на С++?

  • с помощью cin.get()
  • или используя system("pause")
  • или используя функции C, такие как getch() или getchar()?

Правда ли, что использование system("pause") приводит к не переносимому коду и не может работать в UNIX?

Лучше ли использовать cin.get() для приостановки консоли?

Ответ 1

Может быть лучший способ (например, использовать переносимый cin.get()), но хороший путь не существует. Программа, которая выполнила свою работу, должна выйти и вернуть свои ресурсы на компьютер.

И да, любое использование system() приводит к неуправляемому коду, поскольку этот параметр передается оболочке, которая владеет вашим процессом.

Приостановка кода в исходном коде рано или поздно вызывает проблемы:

  • кто-то забывает удалить приостановочный код перед проверкой
    • теперь все рабочие помощники должны задаться вопросом, почему приложение больше не закрывается
    • история версий испорчена
  • #define - ад.
  • Это раздражает всех, кто запускает ваш код с консоли
  • Это очень, очень, очень раздражает, когда вы пытаетесь запустить и завершить свою программу из script; если ваша программа является частью конвейера в оболочке, потому что, если программа не заканчивается, оболочка script или конвейер тоже не будет

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

В качестве альтернативы вы можете сделать этот вариант программы, но лично я никогда не видел программу с опцией --keep-alive-when-dead.

Мораль истории: Это проблема пользователя, а не проблема с программой. Не повреждайте свой код.

Ответ 2

Если вы хотите написать переносимый код на С++, я бы предложил использовать cin.get().

system("PAUSE") работает в Windows, поскольку для этого требуется выполнение команды консоли с именем "PAUSE". Но я не уверен, что другие операционные системы, такие как Linux или другие производные Unix, поддерживают это. Таким образом, он не переносится.

Поскольку С++ уже предлагает cin.get(), я не вижу веских причин использовать C getch().

Ответ 3

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

Я не думаю, что есть один лучший способ, но "принудительно" оживить сценарий ввода типа довольно обычным образом, особенно при отладке (обычно это либо скомпилировано, либо на основе NDEBUG или _DEBUG), вы можете попробовать std::getline следующим образом

inline void wait_on_enter()
{
    std::string dummy;
    std::cout << "Enter to continue..." << std::endl;
    std::getline(std::cin, dummy);
}

С нашим без "входа в продолжение", при необходимости.

Ответ 4

Нет хорошего способа сделать это, но вы должны использовать портативное решение, поэтому избегайте вызовов system(), в вашем случае вы можете использовать cin.get() или getch(), как вы упомянули в своем вопросе, также есть один совет. Сделайте все паузы, управляемые одним (или очень немногим) определением препроцессора.

Например:

Где-то в глобальном файле:

#define USE_PAUSES
#ifndef _DEBUG    //I asume you have _DEBUG definition for debug and don't have it for release build
#undef USE_PAUSES
#endif

Где-то в коде

#ifdef USE_PAUSES
cin.get();
#endif

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

Ответ 5

Какой лучший способ приостановить консоль в программах на С++?

system("pause"); и getch(); (которые поступают из мира DOS, IIRC) являются неспортивными.

Лучше ли использовать cin.get() для приостановки консоли?

Как единственный портативный и стандартный вариант, я бы сказал, что это так, но я лично считаю, что не следует писать интерактивные консольные программы, то есть программы, которые на самом деле приостанавливают консоль или вводят запрос для ввода (если нет веской причины для что, потому что это делает скрипты оболочки намного сложнее). Консольные программы должны взаимодействовать с пользователем через аргументы командной строки (или, по крайней мере, такое взаимодействие должно быть по умолчанию).

На всякий случай вам нужно приостановить программу для моей программы-за-запуска-из-IDE-и-немедленно-закрытого-но-я-не-есть-достаточно-времени-чтобы увидеть причина-причина; не делайте этого. Просто настройте свои IDE или запускайте консольные программы прямо с консоли.

Ответ 6

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

Насколько мне известно, самым большим недостатком cin является то, что вам нужно нажать Return, а не только любой ключ.

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

Я думаю что-то вроде:

char wait_for_key() {
    int key;
    while ( ! (key == key_pressed(ANY)) ) {
          this_thread::yield();
    }
    return convert_virtual_key_to_char(key);
}

Фактическая функция, очевидно, будет сильно отличаться от того, что я написал, в зависимости от используемой библиотеки.

Я знаю, что в следующих библиотеках есть keylisteners (Не стесняйтесь добавлять больше в редактирование, если знаете что-либо.):

Ответ 7

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

Что-то вроде:

void pause() {
    cin.clear();
    cout << endl << "Press any key to continue...";
    cin.ignore();
}

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

Ответ 8

Это работает для меня.

void pause()
{
    cin.clear();
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    std::string dummy;
    std::cout << "Press any key to continue . . .";
    std::getline(std::cin, dummy);
}

Ответ 9

(Мой ответ частично основан на том, что от Yoank, и частично на комментарии Джастина Тайна по другому вопросу.)

cout << endl << "Press <Enter> to continue...";
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cin.get();

Ответ 10

Поздний ответ, но я думаю, что это поможет другим.

Часть имитационной системы ("пауза") имитирует то, что она просит пользователя: "Нажмите любую клавишу, чтобы продолжить..." Итак, нам нужно что-то, что не ждет просто возврата в виде std :: cin.get( ) сделал бы. Даже если у пользователя getch() есть свои проблемы при использовании дважды (второй раз был замечен, чтобы пропустить паузу в целом, если он сразу же снова приостановился после того же нажатия клавиши). Я думаю, что это связано с входным буфером. Систему ("пауза") обычно не рекомендуется, но нам все же нужно что-то подражать тем, что пользователи могут ожидать. Я предпочитаю getch(), потому что он не выступает на экран, и он работает динамически.

Решение состоит в том, чтобы сделать следующее, используя цикл do-while:

void Console::pause()
{ 
    int ch = 0;

    std::cout << "\nPress any key to continue . . . ";

    do {
        ch = getch();
    } while (ch != 0);

    std::cout << std::endl;
} 

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