система ("пауза"); - Чому це неправильно?


131

Ось питання, яке я не зовсім розумію:

Команда system("pause");вивчається новими програмістами як спосіб призупинити програму і чекати, коли введення з клавіатури продовжиться. Однак, здається, багато хто з ветеранів-програмістів нахмуриться як щось, що не слід робити в різній мірі.

Деякі люди кажуть, що це добре використовувати. Деякі кажуть, що використовувати його можна лише тоді, коли ви зачинені у своїй кімнаті, і ніхто не дивиться. Деякі кажуть, що вони особисто прийдуть до вашого будинку і вб'ють вас, якщо ви ним скористаєтесь.

Я сам новий програміст, який не має офіційної підготовки з програмування. Я використовую його, тому що мене вчили користуватися ним. Що я не розумію, це те, що якщо це не те, що потрібно використовувати, то чому я навчив його використовувати? Або, на зворотній стороні, чи справді це не так вже й погано?

Які ваші думки з цього приводу?



5
Мабуть, людям подобається, щоб їхні заклики робити паузу були дійсно ефективними. Іншими словами, "Поспішайте і зупиніться!"
Lee Louviere

63
Вас вчили тому, що вчителі, як правило, погані програмісти
що

Будь ласка, прочитайте цю пораду щодо задавання хороших запитань: [ Як задати ], [Написання ідеального запитання ].
Аді Інбар

9
@wich абсолютно нісенітниця.
Майкл Чурдакіс

Відповіді:


85

Це нахмурилося, тому що це хакер, що стосується платформи, не має нічого спільного з фактичним навчанням програмуванню, а натомість, щоб обійти функцію IDE / OS - вікно консолі, запущене з Visual Studio, закривається, коли програма закінчиться. І так новий користувач не може побачити вихід своєї нової програми.

Вступ в систему ("пауза") запускає командний рядок програми "пауза" в командному рядку Windows і чекає, коли це закінчиться, перш ніж воно продовжить виконання програми - вікно консолі залишається відкритим, щоб ви могли прочитати вихід.

Кращою ідеєю було б поставити точку перерви в кінці та налагодити її, але це знову має проблеми.


6
Visual Studio може запускати програму в двох режимах: з налагодженням або без нього. При запуску в режимі налагодження він зупиниться на першій точці розриву. Якщо у вас немає такого, він запустить програму і закриє консоль. Отже, якщо ви хочете, щоб програма консолі зупинилася, просто встановіть точку перелому або, ще краще, запустіть її без налагодження! Це виконає програму і зупинить консоль.
Іван Месич

Це не лише особливість Visual Studio - якщо ви запускаєте консольну програму з Windows (тобто на відміну від завантаження командного рядка та запуску її звідти), вона також закриється, коли завершиться виконання.
JBentley

2
-1 Повторно “вікно консолі, запущене з Visual Studio, закривається після завершення виконання програми”, ні, лише тоді, коли програма запускається у відладчику. Повторно “запускає командний рядок програми“ пауза ”програма командного рядка, ні такої немає ( pauseє внутрішня команда в cmd.exe). У списку кращих ідей теж сильно бракує.
Ура та хт. - Альф

Я вважаю, що ця відповідь є єдиною, яка стосується аспекту, що це рішення. Він працює навколо поведінки конкретного середовища виконання, яке закриває вікно терміналу, перш ніж ви зможете прочитати вихід програми. Що ви повинні зробити, щоб виправити це середовище. Якщо цього неможливо зробити, скористайтеся цим способом вирішення, можливо, лише якщо IsDebuggerPresent()повернеться true та задокументуйте це рішення належним чином ("чому цей код тут?").
Ульріх Екхардт

43

Це повільно. Це залежить від платформи. Це небезпечно.

Перше: що це робить. Виклик "системи" буквально як введення команди в командний рядок Windows. Для вашої заявки є тонна установка та відстеження, щоб здійснити такий дзвінок - і накладні витрати просто смішні.

Що робити, якщо програма, яка називається "пауза", була поміщена в PATH користувача? Просто виклик системи ("пауза") лише гарантує виконання програми під назвою "пауза" (сподіваємось, що у вас немає виконуваного файлу з назвою "пауза"!)

Просто напишіть власну функцію "Pause ()", яка використовує _getch. Гаразд, звичайно, _getch також залежить від платформи (зверніть увагу: це визначено в "conio.h") - але це набагато приємніше, ніж system()якщо ви розробляєте в Windows, і це має той же ефект (хоча ви надаєте текст з куттером тощо.

В основному: навіщо вводити стільки потенційних проблем, коли можна просто додати два рядки коду та одну включити та отримати набагато більш гнучкий механізм?


61
Для тих, хто скаржиться на залежність платформи, це, звичайно, здається дивним _getch, особливо коли стандартний C ++ надає getchar.
paxdiablo

33
я відчуваю деяку іронію в розрахунку накладних витрат на взаємодію з людиною)
ShPavel

1
@Spagpants: Можливо, ви не розумієте різниці між тим, як отримувати вклад від людини, і генерувати зображення та звуки у людини.
yzt

1
@ Cheersandhth.-Alf - Гм? Коли я писав це, 8 років тому я щойно закінчив налагодження проблеми, яка була викликана "системою (" пауза "), тому що виконувана назва проекту називалася" пауза ", і вона перейде в нескінченний цикл. Моя думка досі стоїть, я не впевнений, чому ти кажеш, що я неправдивий.

2
@paxdiablo getchar потребує введення, а потім натискання клавіші Enter. _getch вимагає просто натискання клавіші, незалежно від того, що це ключ. Для емуляції _getch на Linux вам потрібно 5-6 рядків коду, щоб змінити консольний режим, а потім повернути його до типового. Це не те саме, він робить різні речі. getchar не є заміною для _getch.
Барнак

29
  • повільно: для простої операції потрібно перестрибувати безліч непотрібного коду Windows та окрему програму
  • не портативний: залежно від програми паузи
  • не гарний стиль: робити системний дзвінок слід лише тоді, коли це дійсно необхідно
  • більше введення тексту: Система ("пауза") довша, ніж getchar ()

простий getchar () повинен зробити чудово.


26

Використання system("pause");Ungood Practice ™, оскільки

  • Це зовсім непотрібно .
    Щоб вікно відкрийте консоль програми в кінці , коли ви запускаєте його з Visual Studio, використання Ctrl+ , F5щоб запустити його без налагодження, або інше місце , точку зупину в останній правої фігурної дужки }в main. Тож без проблем у Visual Studio. І, звичайно, жодних проблем, коли ви запускаєте його з командного рядка.

  • Це проблематично і дратує,
    коли ви запускаєте програму з командного рядка. Для інтерактивного виконання потрібно натискати клавішу наприкінці, без жодної мети. І для використання в автоматизації якихось завдань, які pauseдуже небажані!

  • Це не портативно.
    У Unix-land немає стандартної pauseкоманди.

pauseКоманда є внутрішньою cmd.exeкомандою і не можуть бути перевизначені, як помилково стверджував , принаймні , один інший відповідь. Тобто це не ризик для безпеки, а твердження, що AV-програми діагностують його як таке, настільки ж сумнівне, як і заява про переосмислення команди (адже програма C ++, яка systemвикликає позицію, здатна зробити все, що може зробити інтерпретатор команд, і більше). Крім того, хоча цей спосіб призупинення є надзвичайно неефективним за звичайних стандартів програмування на C ++, що в кінці програми для початківців зовсім не має значення.

Отже, твердження в орді відповідей до цього невірні, і головна причина, по якій ви не повинні використовувати system("pause") або будь-яку іншу команду очікування в кінці вашого main, - перший пункт вище: це абсолютно непотрібно, воно абсолютно не виконує мети , це просто дуже нерозумно.


1
Іноді Ungood Practice ™ потрібні для швидких тестів .... те, що ми називаємо "швидким і брудним"
Michael Haephrati

22

Підсумовуючи це, він повинен призупинити виконання програм і здійснити системний виклик та виділити непотрібні ресурси, коли ви могли б використовувати щось таке просто, як cin.get (). Люди користуються системою ("PAUSE"), тому що вони хочуть, щоб програма чекала, поки вони потрапляють, щоб увійти, щоб побачити їх вихід. Якщо ви хочете, щоб програма чекала на введення, є вбудовані функції для тих, які також є платформою і менш вимогливими.

Подальше пояснення в цій статті.


Ого, ти знову! ти тут живеш? LOL У будь-якому випадку, дякую, я почитаю. Тим часом, які ВАШИ думки з цього приводу?
Faken

У мене було те саме питання, коли я вперше розпочав роботу з С кілька років тому, і мене вказали на ту саму статтю. Я особисто використовую getchar ().
Джон Т

Хо-о-у ... я не працював на C ++ деякий час, але так ... є безумовно кращі способи досягнення тих же результатів
ньютопський

16

Ви можете використовувати std::cin.get()з iostream:

#include <iostream> // std::cout, std::cin
using namespace std;

int main() {
   do {
     cout << '\n' << "Press the Enter key to continue.";
   } while (cin.get() != '\n');

   return 0;
}

Крім того, system('pause')йде повільно, і включає в себе файл , який ви , ймовірно , не потрібно: stdlib.h. Він залежить від платформи і фактично викликає "віртуальну" ОС.


3
Мене вчили користуватися System("pause")на першому курсі програмування, але я хотів мати змогу запускати свої програми на своєму Mac, тому мені довелося дізнатися про це cin.get().
daviewales

10

Тому що він не портативний.

pause

є програмою Windows / DoS, тому цей ваш код не працюватиме в Linux. Крім того, як systemправило , не розглядається як дуже хороший спосіб , щоб викликати іншу програму - це, як правило , краще використовувати CreateProcessабо forkчи що - щось подібне.


4

Як зазначено в інших відповідях, ви можете знайти багато причин, щоб цього уникнути. Все це зводиться до однієї причини, яка змушує решту суперечити. System()Функція небезпечна / ненадійна, і не повинна бути введена в програму без необхідності.

У студентському завданні ця умова ніколи не була виконана, і з цієї причини я б провалив завдання, навіть не запустивши програму, якщо був би дзвінок до цього методу. (Це було зрозуміло з самого початку.)


4

Для мене взагалі немає сенсу чекати, перш ніж вийти без причини. Програма, яка виконала свою роботу, повинна просто закінчитися і повернути свої ресурси назад своєму творцю.

Також не мовчки чекати в темному кутку після робочого дня, чекаючи, коли хтось перекине плече.


7
Це дурна відповідь. Частина програми "виконує свою роботу" - це показ результатів своєї роботи користувачеві. Тому він не повинен закінчуватися, поки користувач не повідомить його про те, що вони закінчили його. Програма, яка зникає з екрану користувача наносекунд після того, як відображає його результати, марна.
JBentley

1
@JBentley: Я говорив про ситуацію після показу результатів, якщо такі є. Для відображення результатів існують відповідні шаблони, такі як сигнали, переривання, таймери, прокрутка у вашому терміналі, файли. system("pause")сам по собі нічого не відображає. Програма інтерфейсу командного рядка, яка викликається не з командного рядка і занадто рано закривається, викликається помилково та з неправильними параметрами, а використання system("pause")для обходу неправильно викликаної програми насправді не правильне.
Себастьян Мах

1
Я маю в виду, тільки уявіть собі cat, less, vi, OpenOffice, Mathematica, GNU Octave, що , якби вони використовують system("pause")? Це було б прикро.
Себастьян Мах

2
Так, це буде прикро, але зараз ви конкретно говорите про проблеми system("pause"), тоді як ваша відповідь говорить про "зачекайте, перш ніж вийти", що є набагато більш узагальненою концепцією. Багато з наведених вами прикладів насправді "чекають, перш ніж вийти", поки користувач не повідомить програму, що хоче, щоб вона вийшла. Я погоджуюся, що system("pause")це не гарний спосіб досягти цього і що є кращі рішення, але це не те, що говорить ваша відповідь.
JBentley

1
@JBentley О, абсолютно: якщо затримка / очікування / підказка є частиною семантики програми, pauseгеть!
Гонки легкості на орбіті

3
system("pause");  

помиляється, оскільки він є частиною API API, тому він не працюватиме в інших операційних системах.

Спробуйте використовувати лише об'єкти зі стандартної бібліотеки C ++. Кращим рішенням буде написати:

cin.get();
return 0;

Але це також спричинить проблеми, якщо у вас є інші cins у коді. Тому що після кожного cinви натискаєте Enterабо \nякий є символом пробілу. cinігнорує цього символу і залишає його в буферній зоні, але cin.get()отримує цей залишився символ. Тож контроль над програмою доходить до лінії, return 0і консоль закривається, перш ніж дозволяти вам бачити результати.
Для вирішення цього питання пишемо код наступним чином:

cin.ignore();  
cin.get();  
return 0;

Це трохи вводить в оману. system()є стандартним і не характерним для MS Windows. Однак pauseкоманда оболонки є надбанням DOS і зазвичай зустрічається лише там.
Ульріх Екхардт

1

Ось одна з причин, яку ви не повинні використовувати: вона збирається розігнати більшість антивірусних програм, що працюють на Windows, якщо ви передаєте програму на іншу машину, оскільки це загроза безпеці. Навіть якщо ваша програма складається лише з простого cout << "hello world\n"; system("pause"); важкого ресурсу, і програма отримує доступ до команди cmd, яку антивіруси сприймають як загрозу.


-1

можливість використання системи ("PAUSE"); при створенні невеликих частин вашої програми - це налагодження її самостійно. якщо ви використовуєте його для отримання результатів змінних до та під час кожного процесу, який ви використовуєте, щоб переконатися, що вони працюють належним чином.

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

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


-3

Це все питання стилю. Це корисно для налагодження, але в іншому випадку його не слід використовувати в остаточній версії програми. Насправді це не має значення в питанні пам'яті, тому що я впевнений, що ті хлопці, які винайшли систему ("пауза"), очікували, що вона буде використовуватися часто. З іншого боку, комп’ютери забувають у своїй пам’яті все, що ми використовуємо на комп’ютері в будь-якому випадку, і це не представляє прямої загрози, як динамічне розподілення пам’яті, тому я рекомендую його для налагодження коду, але нічого іншого.


6
Це насправді не має значення щодо пам'яті, тому що я впевнений, що ті хлопці, які винайшли систему ("пауза"), передчували, що вона буде використовуватися часто, насправді не має сенсу. Ніхто цього не "вигадував", pauseбув розроблений для використання в пакетних програмах DOS, його ніколи не передбачалося використовувати таким чином. Крім того, були кращі альтернативи, перш ніж хто-небудь був досить божевільний, щоб набрати фразу system("pause");.
яким
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.