system („pauza”); - Dlaczego jest źle?

135

Oto pytanie, którego nie do końca rozumiem:

Polecenie system("pause");jest nauczane dla nowych programistów jako sposób na wstrzymanie programu i oczekiwanie na kontynuację wprowadzania danych z klawiatury. Jednak wielu doświadczonych programistów wydaje się być postrzegane jako coś, czego nie powinno się robić w różnym stopniu.

Niektórzy mówią, że jest w porządku. Niektórzy twierdzą, że można go używać tylko wtedy, gdy jesteś zamknięty w swoim pokoju i nikt nie patrzy. Niektórzy mówią, że osobiście przyjdą do twojego domu i zabiją cię, jeśli go użyjesz.

Ja sam jestem nowym programistą bez formalnego szkolenia programistycznego. Używam go, ponieważ nauczono mnie, jak go używać. Czego nie rozumiem, to to, że jeśli nie jest to coś, czego można użyć, to dlaczego zostałem nauczony tego używać? A może z drugiej strony, czy naprawdę nie jest tak źle?

Co myślisz na ten temat?

Faken
źródło
related: stackoverflow.com/questions/900666/…
Gordon Gustafson
5
Najwyraźniej ludzie lubią ich wezwania do zatrzymywania się, aby być naprawdę wydajnymi. Innymi słowy: „Pospiesz się i zatrzymaj!”
Lee Louviere
67
Nauczyliście się tego, ponieważ generalnie nauczyciele są złymi programistami
co
Przeczytaj te porady dotyczące zadawania dobrych pytań: [ Jak zadawać ], [Pisanie idealnego pytania ].
Adi Inbar,

Odpowiedzi:

87

Jest źle widziany, ponieważ jest to hack specyficzny dla platformy, który nie ma nic wspólnego z faktyczną nauką programowania, ale zamiast tego obejść funkcję IDE / OS - okno konsoli uruchomione z Visual Studio zamyka się, gdy program zakończy wykonywanie, i tak nowy użytkownik nie widzi wyjścia swojego nowego programu.

Bodging in System („pauza”) uruchamia program „pauza” z wiersza poleceń systemu Windows i czeka na jego zakończenie, zanim będzie kontynuował wykonywanie programu - okno konsoli pozostaje otwarte, więc można odczytać dane wyjściowe.

Lepszym pomysłem byłoby umieszczenie punktu przerwania na końcu i debugowanie go, ale to znowu powoduje problemy.

ravuya
źródło
6
Visual Studio może uruchomić program w dwóch trybach: z debugowaniem lub bez. Po uruchomieniu w trybie debugowania zatrzyma się w pierwszym punkcie przerwania. Jeśli nie masz zdefiniowanego, uruchomi program i zamknie konsolę. Tak więc, jeśli chcesz, aby program konsoli się zatrzymał, po prostu ustaw punkt przerwania lub, jeszcze lepiej, uruchom go bez debugowania! Spowoduje to uruchomienie programu i zatrzymanie konsoli.
Ivan Mesic
To nie tylko cecha Visual Studio - jeśli uruchomisz program konsoli z systemu Windows (tj. W przeciwieństwie do ładowania wiersza poleceń i uruchamiania go stamtąd), zostanie on również zamknięty po zakończeniu wykonywania.
JBentley,
2
−1 Re „okno konsoli uruchamiane z Visual Studio zamyka się po zakończeniu wykonywania programu”, nie, tylko wtedy, gdy program jest uruchamiany w debugerze. Ponownie „uruchamia program„ pauza ”w wierszu poleceń systemu Windows, nie ma takiego ( pausejest to polecenie wewnętrzne cmd.exe). Brakuje również listy lepszych pomysłów.
Pozdrawiam i hth. - Alf
Myślę, że ta odpowiedź jest jedyną, która dotyka aspektu tego, że jest to obejście. Obejmuje zachowanie określonego środowiska wykonawczego, które zamyka okno terminala, zanim będzie można odczytać wyjście programu. To, co powinieneś zrobić, to naprawić to środowisko. Jeśli nie można tego zrobić, zastosuj to obejście, prawdopodobnie tylko wtedy, gdy IsDebuggerPresent()zwraca wartość true i odpowiednio udokumentuj to obejście („dlaczego ten kod jest tutaj?”).
Ulrich Eckhardt
44

Jest wolny. To zależy od platformy. To niepewne.

Po pierwsze: co to robi. Nazywanie „system” jest dosłownie jak wpisywanie polecenia w wierszu poleceń systemu Windows. Jest mnóstwo konfiguracji i porzucania aplikacji, aby wykonać takie wywołanie - a koszty ogólne są po prostu śmieszne.

Co się stanie, jeśli program o nazwie „pauza” zostanie umieszczony w ścieżce użytkownika? Samo wywołanie systemu („pauza”) gwarantuje tylko wykonanie programu o nazwie „pause” (mam nadzieję, że nie masz pliku wykonywalnego o nazwie „pause”!)

Po prostu napisz własną funkcję „Pause ()”, która używa _getch. OK, jasne, _getch jest również zależne od platformy (uwaga: jest zdefiniowane w "conio.h") - ale jest dużo ładniejsze niż system()gdy tworzysz na Windows i ma ten sam efekt (chociaż to Ty jesteś odpowiedzialny za dostarczenie tekstu z cout lub tak).

Zasadniczo: po co wprowadzać tak wiele potencjalnych problemów, skoro można po prostu dodać dwa wiersze kodu i jeden dołączyć i uzyskać znacznie bardziej elastyczny mechanizm?

Jonathan Leffler
źródło
62
Dla kogoś, kto narzeka na zależność od platformy, z pewnością wydaje się to dziwne _getch, zwłaszcza gdy zapewnia to standardowy C ++ getchar.
paxdiablo
33
odczuwam ironię w obliczaniu kosztów interakcji z człowiekiem)
ShPavel
1
@Spagpants: Być może nie rozumiesz różnicy między otrzymywaniem danych wejściowych od człowieka a generowaniem obrazów i dźwięków u człowieka.
od
1
@ Cheersandhth.-Alf - Hm? Kiedy to pisałem, 8 lat temu, właśnie zakończyłem debugowanie problemu, który był spowodowany przez „system („ pauza ”)”, ponieważ nazwa pliku wykonywalnego projektu nazywała się „pauza” i przechodziła w nieskończoną pętlę. Mój punkt widzenia jest nadal aktualny, nie jestem pewien, dlaczego twierdzisz, że się myliłem.
2
@paxdiablo getchar wymaga wprowadzenia danych, a następnie naciśnięcia klawisza Enter. _getch wymaga tylko naciśnięcia klawisza bez względu na to, jaki to klawisz. Aby emulować _getch w systemie Linux, potrzebujesz 5-6 linii kodu, aby zmienić tryb konsoli, a następnie zmienić go z powrotem na domyślny. To nie to samo, robi różne rzeczy. getchar nie zastępuje _getch.
Barnack
30
  • powolny: musi przeskakiwać przez wiele niepotrzebnego kodu systemu Windows i oddzielny program do prostej operacji
  • nieprzenośny: zależny od programu pauzy
  • niezbyt dobry styl: wykonywanie wywołań systemowych powinno być wykonywane tylko wtedy, gdy jest to naprawdę konieczne
  • więcej pisania: System („pauza”) jest dłuższy niż getchar ()

prosta getchar () powinna wystarczyć.

Gavin H.
źródło
26

Używanie system("pause");jest Ungood Practice ™, ponieważ

  • To zupełnie niepotrzebne .
    Aby zachować konsoli otwartym oknie programu na końcu po uruchomieniu go z Visual Studio, stosowania Ctrl+ F5do uruchomienia go bez debugowania, albo umieścić punkt przerwania w ostatniej prawej klamra }z main. Więc nie ma problemu z Visual Studio. I oczywiście nie ma żadnego problemu, gdy uruchamiasz go z wiersza poleceń.

  • Jest to problematyczne i denerwujące,
    gdy uruchamiasz program z wiersza poleceń. Aby wykonać interaktywne wykonanie, musisz nacisnąć klawisz na końcu bez żadnego celu. I do wykorzystania w automatyzacji niektórych zadań, które pausesą bardzo niepożądane!

  • Nie jest przenośny.
    Unix-land nie ma standardowego pausepolecenia.

pausePolecenie to wewnętrzna cmd.exekomenda i nie może być zmieniona, jak błędnie twierdzi się w co najmniej jednej innej odpowiedzi. To znaczy, że nie jest to zagrożenie bezpieczeństwa, a twierdzenie, że programy antywirusowe diagnozują to jako takie, jest równie wątpliwe, jak twierdzenie o nadpisaniu polecenia (w końcu program wywołujący C ++ systemjest w stanie zrobić wszystko, co może zrobić interpreter poleceń, i jeszcze). Ponadto, chociaż ten sposób wstrzymywania jest wyjątkowo nieefektywny w porównaniu ze zwykłymi standardami programowania w C ++, nie ma to żadnego znaczenia na końcu programu nowicjusza.

Tak więc twierdzenia w hordzie odpowiedzi przed tym nie są poprawne, a głównym powodem, dla którego nie powinieneś używać system("pause") ani żadnego innego polecenia czekania na końcu twojego main, jest pierwszy punkt powyżej: jest to całkowicie niepotrzebne, nie służy absolutnie żadnemu celowi , to jest po prostu bardzo głupie.

Pozdrawiam i hth. - Alf
źródło
1
Czasami do szybkich testów potrzebna jest Ungood Practice ™… to, co nazywamy „szybkimi i nieczystymi”
Michael Haephrati
22

Podsumowując, musi wstrzymać wykonywanie programów i wykonać wywołanie systemowe oraz przydzielić niepotrzebne zasoby, gdy można użyć czegoś tak prostego jak cin.get (). Ludzie używają Systemu („PAUSE”), ponieważ chcą, aby program czekał, aż naciśną klawisz Enter, aby zobaczyć swoje dane wyjściowe. Jeśli chcesz, aby program czekał na dane wejściowe, są wbudowane funkcje, które są również wieloplatformowe i mniej wymagające.

Dalsze wyjaśnienia w tym artykule.

John T.
źródło
Wow, znowu ty! czy tutaj mieszkasz? lol Tak czy inaczej, dzięki, trochę poczytam. W międzyczasie, co o tym sądzisz w tej sprawie?
Faken
Miałem to samo pytanie, kiedy zacząłem kilka lat temu po raz pierwszy C, i wskazano mi ten sam artykuł. Osobiście używam getchar ().
John T,
Hej ... Przez jakiś czas nie robiłem C ++, ale tak ... są zdecydowanie lepsze sposoby na osiągnięcie tych samych wyników
Newtopian
17

Możesz skorzystać std::cin.get()z 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;
}

Poza tym, system('pause')jest powolny, a zawiera plik prawdopodobnie nie potrzeba: stdlib.h. Jest zależny od platformy i faktycznie wywołuje „wirtualny” system operacyjny.

Gavriel Feria
źródło
3
Nauczyłem się używać System("pause")na pierwszym roku programowania, ale chciałem mieć możliwość uruchamiania programów na moim Macu, więc musiałem się czegoś nauczyć cin.get().
daviewales
10

Ponieważ nie jest przenośny.

pause

jest programem tylko dla systemu Windows / DOS, więc ten kod nie będzie działał pod Linuksem. Co więcej, systemnie jest powszechnie uważany za bardzo dobry sposób, aby wywołać inny program - jest to zwykle lepiej użyć CreateProcesslub forkczy coś podobnego.

a_m0d
źródło
4

Jak wymieniono w innych odpowiedziach, istnieje wiele powodów, dla których można tego uniknąć. Wszystko sprowadza się do jednego powodu, który sprawia, że ​​reszta jest dyskusyjna. System()Funkcja jest z natury niepewne / niezaufane, i nie powinny być wprowadzane do programu, chyba że jest to konieczne.

W przypadku zadania studenckiego warunek ten nigdy nie został spełniony iz tego powodu nie zaliczyłbym zadania nawet bez uruchamiania programu, gdyby było obecne wywołanie tej metody. (Było to jasne od samego początku.)

Sam Harwell
źródło
4

Dla mnie generalnie nie ma sensu czekać przed wyjściem bez powodu. Program, który wykonał swoją pracę, powinien po prostu zakończyć się i przekazać swoje zasoby twórcy.

Nie można też po cichu czekać w ciemnym kącie po dniu pracy, czekając, aż ktoś się przechyli.

Sebastian Mach
źródło
7
To głupia odpowiedź. Część programu „wykonująca swoją pracę” wyświetla wyniki swojej pracy użytkownikowi. Dlatego nie powinien kończyć się, dopóki użytkownik nie powiadomi go, że skończył z nim. Program, który znika z ekranu użytkownika w nanosekundę po wyświetleniu wyników, jest bezużyteczny.
JBentley
1
@JBentley: Mówiłem o sytuacji po wyświetleniu wyników, jeśli takie istnieją. Do wyświetlania wyników istnieją odpowiednie wzorce, takie jak sygnały, przerwania, liczniki czasu, przewijanie wstecz w terminalu, pliki. system("pause")sam w sobie nic nie wyświetla. Program interfejsu wiersza poleceń, który jest wywoływany nie z linii poleceń i zamyka się zbyt wcześnie, jest wywoływany nieprawidłowo i z niewłaściwymi opcjami, a używanie go system("pause")do obejścia błędnie wywołanego programu nie jest naprawdę właściwe.
Sebastian Mach,
1
To znaczy, proszę sobie wyobrazić cat, less, vi, OpenOffice, Mathematica, GNU Octave, co, jeśli oni by użyć system("pause")? To byłoby denerwujące.
Sebastian Mach,
2
Tak, byłoby to irytujące, ale teraz mówisz konkretnie o problemach programu system("pause"), podczas gdy twoja odpowiedź mówi o „poczekaniu przed wyjściem”, co jest znacznie bardziej uogólnioną koncepcją. Wiele z przykładów, które podałeś, faktycznie "poczekaj przed zakończeniem", dopóki użytkownik nie poinformuje programu, że chce, aby zakończył. Zgadzam się, że system("pause")nie jest to dobry sposób na osiągnięcie tego celu i że istnieją lepsze rozwiązania, ale nie tak mówi twoja odpowiedź.
JBentley,
1
@JBentley Och, absolutnie: jeśli opóźnienie / oczekiwanie / zachęta jest częścią semantyki programu, pauseprecz!
Wyścigi lekkości na orbicie
4
system("pause");  

jest błędne, ponieważ jest częścią interfejsu API systemu Windows, więc nie będzie działać w innych systemach operacyjnych.

Powinieneś spróbować użyć tylko obiektów ze standardowej biblioteki C ++. Lepszym rozwiązaniem będzie napisanie:

cin.get();
return 0;

Ale spowoduje to również problemy, jeśli masz inne cinznaki w swoim kodzie. Ponieważ po każdym cindotknięciu znaku Enterlub, \nktóry jest znakiem spacji. cinignoruje ten znak i pozostawia go w strefie buforowej, ale cin.get()otrzymuje ten pozostały znak. Tak więc kontrola programu dociera do linii, return 0a konsola zostaje zamknięta przed wyświetleniem wyników.
Aby rozwiązać ten problem, piszemy kod w następujący sposób:

cin.ignore();  
cin.get();  
return 0;
Sepideh Abadpour
źródło
2
To trochę mylące. system()jest standardem i nie jest specyficzne dla MS Windows. Jednak pausepolecenie powłoki jest dziedzictwem DOS i zwykle można je znaleźć tylko tam.
Ulrich Eckhardt
1

Oto jeden powód, dla którego nie powinieneś go używać: wkurza większość programów antywirusowych działających w systemie Windows, jeśli przekazujesz program na inną maszynę, ponieważ stanowi zagrożenie dla bezpieczeństwa. Nawet jeśli twój program składa się tylko z prostego, cout << "hello world\n"; system("pause"); ma duże zasoby i program uzyskuje dostęp do polecenia cmd, które antywirusy postrzegają jako zagrożenie.

Andreas DM
źródło
-1

profesjonaliści do korzystania z systemu („PAUZA”); tworzenie małych części programu służy do samodzielnego debugowania. jeśli użyjesz go do uzyskania wyników zmiennych przed i po każdym używanym procesie, aby upewnić się, że działają one poprawnie.

Po przetestowaniu i wprowadzeniu pełnego obrotu z resztą rozwiązania należy usunąć te linie. przydaje się przy testowaniu algorytmu zdefiniowanego przez użytkownika i upewnianiu się, że wykonujesz czynności we właściwej kolejności, aby uzyskać pożądane wyniki.

W żadnym wypadku nie chcesz używać tego w aplikacji po przetestowaniu i upewnieniu się, że działa poprawnie. Jednak pozwala na śledzenie wszystkiego, co się dzieje, na bieżąco. W ogóle nie używaj go do aplikacji użytkowników końcowych.

Nikogo w szczególności
źródło
-3

To kwestia stylu. Jest to przydatne do debugowania, ale poza tym nie powinno być używane w ostatecznej wersji programu. Naprawdę nie ma to znaczenia w kwestii pamięci, ponieważ jestem pewien, że ci faceci, którzy wymyślili system („pauza”), spodziewali się, że będzie on często używany. Z innej perspektywy komputery są ograniczane w pamięci dla wszystkiego, czego używamy na komputerze i nie stanowi to bezpośredniego zagrożenia, takiego jak dynamiczna alokacja pamięci, więc poleciłbym to do debugowania kodu, ale nic więcej.

Jason A.
źródło
6
To naprawdę nie ma znaczenia w kwestii pamięci, ponieważ jestem pewien, że ci faceci, którzy wymyślili system („pauza”), spodziewali się, że będzie on często używany, naprawdę nie ma to żadnego sensu. Nikt tego nie „wymyślił”, pausezostał zaprojektowany do użytku w programach wsadowych DOS, nigdy nie był przeznaczony do używania w taki sposób. Co więcej, istniały o wiele lepsze alternatywy, zanim ktokolwiek był na tyle szalony, by wpisać to zdanie system("pause");.
który