Pauzeer console in C++-programma

Wat is de beste manier om de console te pauzeren in C++-programma’s?

  1. met behulp van cin.get()
  2. of met behulp van system("PAUSE")
  3. of C-functies gebruiken zoals getch()of getchar()?

Is het waar dat het gebruik van system("PAUSE")leidt tot niet-overdraagbare code en niet kan werken in UNIX?

Is cin.get() beter om te gebruiken om de console te pauzeren?


Antwoord 1, autoriteit 100%

Er is misschien een beste manier (zoals het gebruik van de draagbare cin.get()), maar een goedemanier bestaat niet. Een programma dat zijn werk heeft gedaan, moet stoppen en zijn bronnen teruggeven aan de computer.

En ja, elk gebruik van system()leidt tot ondraagbare code, omdat de parameter wordt doorgegeven aan de shell die eigenaar is van uw proces.

Het hebben van pauze-code in je broncode veroorzaakt vroeg of laat problemen:

  • iemand vergeet de pauzecode te verwijderen voordat hij incheckt
    • nu moeten alle collega’s zich afvragen waarom de app niet meer sluit
    • versiegeschiedenis is aangetast
  • #defineis een hel
  • het is vervelend voor iedereen die uw code vanaf de console uitvoert
  • het is heel, heel, heel vervelend als je probeert je programma te starten en te beëindigen vanuit een script; quasi vervelend als je programma deel uitmaakt van een pijplijn in de shell, want als het programma niet eindigt, zal het shellscript of de pijplijn dat ook niet doen

Verken in plaats daarvan uw IDE. Het heeft waarschijnlijk een optie om het consolevenster niet te sluiten na het uitvoeren. Zo niet, dan is het een goede rechtvaardiging voor jou als ontwikkelaar die zijn/haar geld waard is om altijd een consolevenster in de buurt open te hebben.

Je kunt er ook een programma-optie van maken, maar ik heb persoonlijk nog nooit een programma gezien met een optie --keep-alive-when-dead.

Moraal van het verhaal:dit is het probleem van de gebruiker en niet het probleem van het programma. Besmeur uw code niet.


Antwoord 2, autoriteit 34%

Als je draagbare C++-code wilt schrijven, raad ik je aan cin.get()te gebruiken.

system("PAUSE")werkt op Windows, omdat het de uitvoering van een consoleopdracht met de naam “PAUSE” vereist. Maar ik weet niet zeker of andere besturingssystemen zoals Linux of andere Unix-derivaten dat ondersteunen. Dus dat is meestal niet draagbaar.

Aangezien C++ al cin.get()biedt, zie ik geen dwingende reden om C getch()te gebruiken.


Antwoord 3, autoriteit 7%

De beste manierhangt sterk af van het (de) platform(en) waarop wordt getarget, het debuggen versus het gebruik van de release, enz.

Ik denk niet dat er één bestemanier is, maar om op een vrij algemene manier een wachten op enter-typescenario te “forceren”, vooral bij het debuggen (meestal wordt dit ofwel in of uit gecompileerd gebaseerd op NDEBUGof _DEBUG), kunt u std::getlineals volgt proberen

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

Met onze zonder de “enter om verder te gaan”, indien nodig.


Antwoord 4, autoriteit 4%

Wat is de beste manier om de console te pauzeren in C++-programma’s?

system("pause");en getch();(die afkomstig zijn uit de DOS-wereld, IIRC) zijn beide ondraagbaar.

Is cin.get() beter om te gebruiken om de console te pauzeren?

Als de enige draagbareen standaardoptie, zou ik zeggen van wel, maar persoonlijk vind ik dat je geen interactieve consoleprogramma’s moet schrijven, dwz programma’s die de console of prompt voor invoer (tenzij daar een echtgoede reden voor is, want dat maakt shellscripting veel moeilijker). Consoleprogramma’s zouden met de gebruiker moeten communiceren via opdrachtregelargumenten (of dat soort interactie zou in ieder geval de standaard moeten zijn).

Voor het geval je het programma wilt pauzeren voor het mijn-programma-is-gelanceerd-van-de-IDE-en-onmiddellijk-gesloten-maar-ik-niet-genoeg-tijd-om-te-zien -de-resultaat reden doe dat niet. Configureer gewoon uw IDE of start consoleprogramma’s rechtstreeks vanaf de console.


Antwoord 5

Er is geen goedemanier om dat te doen, maar je moet een draagbare oplossing gebruiken, dus vermijd system()-aanroepen, in jouw geval zou je cin.get()of getch()zoals je in je vraag zei, er is ook één advies. Maak allepauzes aangestuurd door één (of zeer weinig) preprocessor-definities.

Bijvoorbeeld:

Ergens in globaal bestand:

#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

Ergens in code

#ifdef USE_PAUSES
cin.get();
#endif

Dit is geen universeel advies, maar je moet jezelf beschermen tegen het plaatsen van pauzesin release-builds en deze zouden gemakkelijk te controleren moeten zijn, mijn genoemde algemene bestandis misschien niet zo globaal , omdat veranderingen daarin een erg lange compilatie kunnen veroorzaken.


Antwoord 6

(Mijn antwoord is gedeeltelijk gebaseerd op dat van Yoank, en gedeeltelijk op een commentaardoor Justin Timeop een andere vraag.)

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

Antwoord 7

Ik wil er alleen aan toevoegen dat er een manier is om te krijgen wat je wilt, maar dat je hiervoor een bibliotheek van derden moet gebruiken (of dat je de platformafhankelijke code zelf schrijft).

Wat mij betreft is het grootste nadeel van cin dat je op Return moet drukken, en niet zomaar een toets.

Ervan uitgaande dat u een toets-listener had, zou u vrij gemakkelijk een functie kunnen schrijven die wacht tot de gebruiker op elketoets drukt. Het vinden van een platformonafhankelijke key-listener is echter geen triviale taak en vereist waarschijnlijk dat u delen van een grotere bibliotheek laadt.

Ik denk iets in de trant van:

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

De eigenlijke functie zou natuurlijk heel anders zijn dan wat ik schreef, afhankelijk van de bibliotheek die je gebruikt.

Ik weet dat de volgende bibliotheken keylisteners hebben (Voel je vrij om meer toe te voegen in een bewerking als je die kent.):


Antwoord 8

Ik heb altijd een paar regels code gebruikt die de invoerstroom van alle tekens wissen en vervolgens wachten tot de invoer wordt genegeerd.

Zoiets als:

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

En als ik het in het programma nodig heb, heb ik mijn eigen pauze(); functie, zonder de overhead van een systeempauze. Dit is alleen echt een probleem bij het schrijven van consoleprogramma’s die je open wilt houden of op een bepaald punt gefixeerd wilt blijven.


Antwoord 9

Dit werkt voor mij.

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);
}

Antwoord 10

Lage reactie, maar ik denk dat het anderen zal helpen.

Een deel van het imiteren van systeem (“pauze”) is het imiteren van wat het de gebruiker vraagt: “Druk op een willekeurige toets om door te gaan …” Dus we hebben iets nodig dat niet wacht op een terugkeer als std::cin .get() zou doen. Zelfs getch() heeft zijn problemen wanneer het twee keer wordt gebruikt (de tweede keer is opgemerkt dat het pauzeren over het algemeen overslaat als het daarna onmiddellijk opnieuw wordt gepauzeerd bij dezelfde toetsdruk). Ik denk dat het te maken heeft met de invoerbuffer. Systeem (“pauze”) wordt meestal niet aanbevolen, maar we hebben nog steeds iets nodig om te imiteren wat gebruikers misschien al verwachten. Ik geef de voorkeur aan getch() omdat het niet naar het scherm echoot en het dynamisch werkt.

De oplossing is om het volgende te doen met een do-while-lus:

void Console::pause()
{ 
    int ch = 0;
    std::cout << "\nPress any key to continue . . . ";
    do {
        ch = getch();
    } while (ch != 0);
    std::cout << std::endl;
} 

Nu wacht het totdat de gebruiker op een willekeurige toets drukt. Als het twee keer wordt gebruikt, wacht het opnieuw op de gebruiker in plaats van over te slaan.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes