Najlepsza odpowiedź
To jedno z moich ulubionych pytań dotyczących dyskwalifikacji C ++ ekspertów .
Oczywiście system („PAUSE”) oznacza utworzenie powłoki systemu operacyjnego i pozwolenie mu na wykonanie polecenia „PAUSE”.
Właściwie to działa tylko w systemie Windows, gdzie NIE jest to problem z bezpieczeństwem , ponieważ„ PAUSE ”jest wewnętrznym poleceniem powłoki, które nie wywołuje żadnego programu zewnętrznego (chyba że powłoka systemu sama została zhakowana… ale niż masz inny problem)
W systemie Windows nie jest to nawet duży „problem z wydajnością”: obraz CMD.EXE jest już prawie na pewno w pamięci RAM, segment danych CMD jest dość mały i… cóż … Prosisz o WSTRZYMANIE (nie uruchamianie tak szybko, jak to możliwe!)
W systemach innych niż okna , to nie zadziała (może nie być polecenia PAUSE) i jest to wyciek bezpieczeństwa (ktoś może n stwórz program PAUSE, aby wykonać swoje własne zadanie zamiast twojego).
Więc jeśli nie celujesz w swoją jedyną maszynę i swój jedyny system operacyjny, nie będzie to przenośne i może być nawet niebezpieczne.
Ale teraz problem wygląda następująco: „ co robić ?”
Fantastycznie jest zobaczyć, jak większość odpowiedź brzmi… ŹLE , ponieważ… nie mogą działać!
Zobaczmy, dlaczego:
Twój program cin
-s dwie liczby całkowite, pokazuje wyniki i… czy musi czekać czy wyjść?
Załóżmy chcesz poczekać: jak odpowiesz na cin >> a
i cin >> b
?
Twoje dane wejściowe będą wyglądać następująco:
12\n
34\n
MUSISZ wpisać te f. .ing zwraca, ponieważ musisz wyjść z trybu wprowadzania konsoli.
Teraz cin >> a
zużyje „12”. Zwrot pozostanie w buforze.
cin >> b
zajmie wszystkie spacje (w tym zwroty) aż do pierwszej spacji, a następnie wszystkich cyfr. Zużywa „\ n34” (i ustawi b = 34).
Jest do momentu, gdy w buforze wejściowym nastąpi zwrot. Zobaczmy teraz, jak wszyscy eksperci FAIL!
- używają
cin.get()
: ŹLE : Spowoduje to odczytanie jednego znaku i kontynuację. W buforze wejściowym jest jeden znak, więc nie zatrzyma się ! - użyj
cin.ignore()
: ŹLE: W buforze nadal jest ten zwrot. Ignorujesz to… i idziesz dalej. Bez przerwy .
Jak więc to zrobić?
W tym konkretnym przykładzie musisz zignorować wszystko, co jest w buforze, aż do powrotu, a następnie poprosić o coś innego do zignorowania:
cin.clear(); // clear an eventual "bad read" flag
cin.ignore(BIG\_NUMBER,’\n’); // ignore all remaining pending input
cin.get(); //just read one more!
BIG\_NUMBER, to… wszystko większe niż znaki, na których możesz wpisać konsoli przed naciśnięciem klawisza Enter.
Standardowy sposób uzyskania tego numeru to
numeric\_limits
(don nie zapomnij #include
)
A więc na koniec…
void pause()
{
cin.clear();
cin.ignore(numeric\_limits
cin.get();
}
być odpowiednią funkcją pauzy .
Ale teraz powiedz mi:
A co, jeśli ktoś wpisze
12abcd\n
??
Pierwszy odczyt wyświetli„ 12 ”, a drugi„ a… ”i zakończy się niepowodzeniem (nie jest to cyfra!). B w ogóle nie jest czytany.
Następnie pause()
wyczyści „zły bit” i odrzuci abcd\n
, a następnie przeczytaj „1” i szczęśliwie zakończ.
Morał : podczas czytania liczb zawsze sprawdzaj, czy odczyt się nie powiódł i odrzuć ewentualne błędne dane wejściowe:
while(!(cin >> b))
{ cin.clear(); cin.ignore(numeric\_limits
Ale wymaga to również zarządzania podpowiedzi i tak dalej … i prowadzi zbyt daleko od rzeczywistego celu.
Odpowiedź
To nie jest czyste rozwiązanie. Niektórzy ludzie mogą nazywać to „hack”, a inni „obejście”.
Widzisz, jedną z fajnych właściwości języka C jest jego przenośność . A dzięki składni systemowej („PAUSE”) tracisz tę przenośność, ponieważ zależy to od konsoli używanej do uruchamiania programu.
A teraz, jakie są alternatywy? Niestety nie ma idealnie czystego rozwiązania. Widziałem ludzi używających tej składni
std::cout << “Press any key to continue…”;
std::cin >> Some\_variable\_you\_declared\_in\_advance;
Zasadniczo to tylko kolejny hack, wykorzystujący strumień do wstrzymywania programu. Ale w ten sposób nie tracisz przenośności.
Jednym z najczystszych rozwiązań, jakie znam, jest to (ale jest bardzo zależne od gustu):
void pause () {
std::cin.ignore();
}
W ten sposób możesz użyć własnej funkcji pauzy . Zasadniczo czyta jeden znak i ignoruje go, co jest dokładnie tym, co chcesz osiągnąć. Ale jak powiedziałem, z pewnością nie jest to najlepsze rozwiązanie, tylko moje ulubione rozwiązanie.