Wie simulieren Sie “Drücken Sie eine beliebige Taste, um fortzufahren?”

Lesezeit: 10 Minuten

Wie simulieren Sie Drucken Sie eine beliebige Taste um fortzufahren
seinaboutcode

Ich versuche, ein C++-Programm zu schreiben, in dem der Benutzer, wenn er ein beliebiges Zeichen über die Tastatur eingibt, zur nächsten Codezeile wechseln sollte.

Hier ist mein Code:

char c;

cin>>c;

cout<<"Something"<<endl;

aber das funktioniert nicht, weil es nur zur nächsten Zeile wechselt, wenn ich ein Zeichen eingebe und dann ENTER drücke.

ODER

Wenn ich das verwende

cin.get() or cin.get(c)

Es geht zur nächsten Anweisungszeile, wenn ich die Eingabetaste drücke.

Aber ich wollte, dass es bei jeder Taste, die auf der Tastatur gedrückt wird, zur nächsten Zeile wechselt, wie kann das gemacht werden?

  • Soweit ich weiß, besteht das Problem darin, dass Ihre Shell darauf wartet, dass Sie ENTER oder EOF drücken, und dann Ihr Programm sich um alles kümmern lässt, was sich im Puffer befindet, oder so ähnlich. Vielleicht kann jemand mit etwas mehr Wissen eine echte Erklärung liefern. Aber ich denke, es ist nicht so einfach, wie es zunächst scheint.

    – Lukas

    19. September 2009 um 21:02 Uhr

  • Der bei weitem einfachste Weg, dies zu handhaben, und der einzige tragbare Weg, besteht darin, Ihre Eingabeaufforderung von „Drücken Sie eine beliebige Taste, um fortzufahren“ in „Drücken Sie die Eingabetaste, um fortzufahren“ zu ändern.

    – Mayoff ausrauben

    23. Februar 12 um 4:44 Uhr

  • @Lucas – Ich verwende Mac mit xcode.

    – sein Aboutcode

    23. Februar 2012 um 19:25 Uhr


  • @Lucas: Es ist nicht die Shell, es ist das Programm selbst.

    – Keith Thompson

    23. Februar 2012 um 19:25 Uhr

  • @KeithThompson: Das ist mehr als zwei Jahre her, aber ich glaube, ich habe versucht, darauf hinzuweisen, dass die Eingabewarteschlange nicht vom Benutzerprozess, sondern im Kernel behandelt wird.

    – Lukas

    24. Februar 12 um 3:13 Uhr


Unter Windows:

system("pause");

und auf Mac und Linux:

system("read");

gibt “Drücken Sie eine beliebige Taste, um fortzufahren …” aus und wartet offensichtlich darauf, dass eine Taste gedrückt wird. Ich hoffe das war was du meintest

  • system ruft externes Programm auf. Sie müssen kein externes Programm aufrufen, um auf eine Taste zu warten! Es ist, als würde man eine andere Person anrufen, damit sie den Computer einschaltet, während man davor sitzt – das ist eine langsame Lösung.

    – IngwerPlusPlus

    25. August 14 um 9:51 Uhr


  • Stimmt, aber es ist nur eine Zeile lang! Manchmal lohnt es sich einfach nicht, dem Computer einige Zyklen zu sparen…

    – Elliot Cameron

    24. November 14 um 17:02 Uhr

  • Vergessen Sie langsam, es ruft das erste Programm mit dem Namen “pause” auf, das es zufällig in PATH findet, und gibt ihm die Berechtigungsstufe des aufrufenden Programms. Selbst wenn Sie als Student nur Ihren eigenen Code testen, ist dies immer noch ein massives Sicherheitsrisiko.

    – Anne Quinn

    14. Dezember 14 um 11:11 Uhr

  • @XDfaceme – pause ist ein tatsächliches Programm, das system() Windows zur Ausführung auffordert. Wenn es jedoch ein anderes Programm namens “Pause” gibt und Windows dieses Programm zuerst findet, wird es stattdessen ausgeführt. Ich nehme an, ich habe die Bedeutung vielleicht ein wenig übertrieben, aber es ist immer noch einfacher, einfach cin.get() zu verwenden und die Eingabetaste zu drücken, um ein Programm anzuhalten / fortzusetzen

    – Anne Quinn

    27. Januar 15 um 23:32 Uhr

  • Ich bin kein Fan von Absolutheiten. Eine pauschale Aussage zu machen, dass system(“pause”) ein Sicherheitsrisiko ist und dass es schlecht ist, selbst wenn Sie Ihren eigenen Code testen, bläst die Dinge hier völlig überproportional auf. cin.get() könnte die richtige Lösung sein, aber es löst nicht die Frage, die gestellt wurde … cin.get() antwortet nur, nachdem “enter” oder “return” gedrückt wurden. Die Frage war speziell, auf jeden Tastendruck zu reagieren. system(“pause”) macht genau das. Zunächst einmal ist die einzige Stelle, an der ich dies als nützlich angesehen habe, in einer Entwicklerklasse beim Debuggen von Visual Studio, daher denke ich, dass system (“pause”) funktioniert

    – Gregor

    4. September 17 um 23:07 Uhr

Wie simulieren Sie Drucken Sie eine beliebige Taste um fortzufahren
Vinay Sajip

Wenn Sie Windows verwenden, können Sie verwenden kbhit() die Teil der Microsoft-Laufzeitbibliothek ist. Wenn Sie Linux verwenden, können Sie implementieren kbhit daher (Quelle):

#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>

int kbhit(void)
{
  struct termios oldt, newt;
  int ch;
  int oldf;

  tcgetattr(STDIN_FILENO, &oldt);
  newt = oldt;
  newt.c_lflag &= ~(ICANON | ECHO);
  tcsetattr(STDIN_FILENO, TCSANOW, &newt);
  oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
  fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

  ch = getchar();

  tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
  fcntl(STDIN_FILENO, F_SETFL, oldf);

  if(ch != EOF)
  {
    ungetc(ch, stdin);
    return 1;
  }

  return 0;
}

Aktualisieren: Die obige Funktion funktioniert unter OS X (zumindest unter OS X 10.5.8 – Leopard, daher würde ich erwarten, dass sie unter neueren Versionen von OS X funktioniert). Dies Kern kann gespeichert werden als kbhit.c und sowohl auf Linux als auch auf OS X mit kompiliert

gcc -o kbhit kbhit.c

Beim Laufen mit

./kbhit

Es fordert Sie zu einem Tastendruck auf und wird beendet, wenn Sie eine Taste drücken (nicht auf die Eingabetaste oder druckbare Tasten beschränkt).

@Johnsyweb – Bitte erläutern Sie, was Sie mit “detaillierte kanonische Antwort” und “alle Bedenken” meinen. Auch zu “plattformübergreifend”: Mit dieser Implementierung von kbhit() Sie können dieselbe Funktionalität in einem C++-Programm unter Linux/Unix/OS X/Windows haben – auf welche anderen Plattformen beziehen Sie sich möglicherweise?

Weiteres Update für @Johnsyweb: C++-Anwendungen leben nicht in einer hermetisch abgeschlossenen C++-Umgebung. Ein wichtiger Grund für den Erfolg von C++ ist die Interoperabilität mit C. Alle Mainstream-Plattformen sind mit C-Schnittstellen implementiert (auch wenn die interne Implementierung C++ verwendet), sodass Ihre Rede von „Legacy“ fehl am Platz zu sein scheint. Und da wir über eine einzelne Funktion sprechen, warum brauchen Sie C++ dafür (“C mit Klassen”)? Wie ich bereits erwähnt habe, können Sie in C++ schreiben und auf diese Funktionalität einfach zugreifen, und die Benutzer Ihrer Anwendung werden sich wahrscheinlich nicht darum kümmern wie du hast es umgesetzt.

  • Es ist eine Schande, dass es keine Standardmethode gibt, um mit der Konsole umzugehen, Sie müssen immer etwas OS-Magik verwenden

    – Varga

    20. September 2009 um 0:29 Uhr

  • @Johnsyweb: Danke Sie, aber Ihr Beispiel zeigt Funktionen, die mich an C++ deprimieren. Deine kbhit() Funktion deklariert a terminal_settings Variable in einer Zeile, die nichts zu tun scheint und doch alles tut. Einige mögen es nett finden, aber ich finde es undurchsichtig bis zur Unlesbarkeit.

    – Vinay Sajip

    25. Februar 2012 um 23:05 Uhr


  • @VinaySajip: Meine Implementierung verwendet RAII, eines der wichtigsten Idiome in C++. Obwohl dies in diesem Beispiel nicht unbedingt erforderlich ist, habe ich festgestellt, dass es eine gute Angewohnheit ist, sich darauf einzulassen, wenn Sie einen Zustand speichern und wiederherstellen möchten.

    – Johnsyweb

    26. Februar 2012 um 2:00 Uhr

  • @Johnsyweb: Ich kenne RAII und die Vorteile, die es bringt, ich bin selbst ein alter C++-Hasen. Mein Punkt bleibt: Es gibt keine klare Verbindung zwischen der Erklärung und dem, was sie hinter den Kulissen tut. Auch wenn es glänzende C++-Ausdrücke anstelle von einfachem altem C verwendet, bin ich der Ansicht, dass es wenig dazu beiträgt, etwas zu beleuchten, und viel dazu beiträgt, zu verschleiern, was vor sich geht. Dies ist in keiner Weise an Sie persönlich gerichtet – es ist nur eine Meinung darüber, wie C++ verwendet werden kann, um Code zu erstellen, der unnötig schwer zu verstehen ist. Ich steige jetzt aus meiner Seifenkiste, sagte nuff.

    – Vinay Sajip

    26. Februar 12 um 21:53 Uhr


  • Es ist nett und alles, fängt aber immer noch irgendwelchen vorherigen Müll auf der stdin 🙂

    – Thiago

    25. März 15 um 15:52 Uhr

Es gibt keine vollständig tragbare Lösung.

Frage 19.1 des comp.lang.c FAQ deckt dies ausführlich ab, mit Lösungen für Windows, Unix-ähnliche Systeme und sogar MS-DOS und VMS.

Eine kurze und unvollständige Zusammenfassung:

  • Du kannst den … benutzen curses Bücherei; Anruf cbreak() gefolgt von getch() (Nicht zu verwechseln mit der Windows-spezifischen getch()Funktion). Beachten Sie, dass curses übernimmt im Allgemeinen die Kontrolle über das Terminal, daher ist dies wahrscheinlich übertrieben.
  • Kannst du vielleicht verwenden ioctl() um die Terminaleinstellungen zu manipulieren.
  • Auf POSIX-kompatiblen Systemen tcgetattr() und tcsetattr() kann eine bessere Lösung sein.
  • Unter Unix können Sie verwenden system() um die anzurufen stty Befehl.
  • Unter MS-DOS können Sie verwenden getch() oder getche().
  • Auf VMS (jetzt OpenVMS genannt) ist die Bildschirmverwaltung (SMG$)-Routinen könnten den Zweck erfüllen.

Alle diese C-Lösungen sollten in C++ gleich gut funktionieren; Ich kenne keine C++-spezifische Lösung.

  • All diese plattformübergreifenden Lösungen könnten mit jemandem auskommen, der eine Funktion schreibt, die so implementiert ist, dass sie abhängig von Ihrer Plattform das Richtige tut, mit vielen Präprozessoren, um festzustellen, was diese Plattform ist.

    – Goldesel

    21. Januar 14 um 16:21 Uhr

1644316330 317 Wie simulieren Sie Drucken Sie eine beliebige Taste um fortzufahren
Fett X

In Windows erreicht dieses kurze Programm das Ziel: getch hält die Konsole an, bis eine Taste gedrückt wird (https://www.geeksforgeeks.org/difference-getchar-getch-getc-getche/)

#include<iostream.h>
#include<conio.h>

using namespace std;

void  check()
{
    char chk; int j;
    cout<<"nnPress any key to continue...";
    chk=getch();
    j=chk;
    for(int i=1;i<=256;i++)
      if(i==j) break;
    clrscr();
}

void main()
{
    clrscr();
    check();
    cout<<"nnIt works!";
    getch();
}

Zu beachten ist, dass getch nicht Teil der Standardbibliothek ist.

Um diese Funktionalität zu erreichen, könnten Sie verwenden ncurses Bibliothek, die sowohl unter Windows als auch unter Linux (und MacOS, soweit ich weiß) implementiert wurde.

  • Nun, das ist eine Art Aufgabe, bei der ich keine externen Bibliotheken usw. verwenden kann, also nur im “Kapitelkontext” lox bleiben muss.

    – sein Aboutcode

    19. September 2009 um 19:48 Uhr

  • Dann besteht die einzige Option darin, die erforderliche Funktionalität für jedes Betriebssystem zu implementieren, das Sie unterstützen möchten.

    – Kirill W. Ljadwinski

    19. September 2009 um 20:01 Uhr

  • ncurses ist mehr oder weniger ein VT200-Client. Ein bisschen übertrieben, um einfach aus dem TTY zu lesen.

    – Grauschimmer

    19. September 2009 um 20:11 Uhr

1644316330 607 Wie simulieren Sie Drucken Sie eine beliebige Taste um fortzufahren
Gemeinschaft

Ich habe mir angesehen, was Sie zu erreichen versuchen, weil ich mich erinnere, dass ich dasselbe tun wollte. Inspiriert von Vinay habe ich etwas geschrieben, das für mich funktioniert und das ich irgendwie verstehe. Aber ich bin kein Experte, also seien Sie bitte vorsichtig.

Ich weiß nicht, woher Vinay weiß, dass Sie Mac OS X verwenden. Aber es sollte mit den meisten Unix-ähnlichen Betriebssystemen so funktionieren. Wirklich hilfreich, da Ressource ist opengroup.org

Achten Sie darauf, den Puffer zu leeren, bevor Sie die Funktion verwenden.

#include <stdio.h>
#include <termios.h>        //termios, TCSANOW, ECHO, ICANON
#include <unistd.h>     //STDIN_FILENO


void pressKey()
{
    //the struct termios stores all kinds of flags which can manipulate the I/O Interface
    //I have an old one to save the old settings and a new 
    static struct termios oldt, newt;
    printf("Press key to continue....n");

    //tcgetattr gets the parameters of the current terminal
    //STDIN_FILENO will tell tcgetattr that it should write the settings
    // of stdin to oldt
    tcgetattr( STDIN_FILENO, &oldt);
    //now the settings will be copied 
    newt = oldt;

    //two of the c_lflag will be turned off
    //ECHO which is responsible for displaying the input of the user in the terminal
    //ICANON is the essential one! Normally this takes care that one line at a time will be processed
    //that means it will return if it sees a "n" or an EOF or an EOL
    newt.c_lflag &= ~(ICANON | ECHO );      

    //Those new settings will be set to STDIN
    //TCSANOW tells tcsetattr to change attributes immediately. 
    tcsetattr( STDIN_FILENO, TCSANOW, &newt);

    //now the char wil be requested
    getchar();

    //the old settings will be written back to STDIN
    tcsetattr( STDIN_FILENO, TCSANOW, &oldt);

}


int main(void)
{
  pressKey();
  printf("ENDn");
  return 0;
}

O_NONBLOCK scheint auch ein wichtiges Flag zu sein, aber es hat nichts für mich geändert.

Ich schätze es, wenn Leute mit etwas tieferem Wissen dies kommentieren und Ratschläge geben würden.

  • Nun, das ist eine Art Aufgabe, bei der ich keine externen Bibliotheken usw. verwenden kann, also nur im “Kapitelkontext” lox bleiben muss.

    – sein Aboutcode

    19. September 2009 um 19:48 Uhr

  • Dann besteht die einzige Option darin, die erforderliche Funktionalität für jedes Betriebssystem zu implementieren, das Sie unterstützen möchten.

    – Kirill W. Ljadwinski

    19. September 2009 um 20:01 Uhr

  • ncurses ist mehr oder weniger ein VT200-Client. Ein bisschen übertrieben, um einfach aus dem TTY zu lesen.

    – Grauschimmer

    19. September 2009 um 20:11 Uhr

1644316330 333 Wie simulieren Sie Drucken Sie eine beliebige Taste um fortzufahren
Keith Thompson

Sie könnten die Microsoft-spezifische Funktion verwenden _getch:

#include <iostream>
#include <conio.h>
// ...
// ...
// ...
cout << "Press any key to continue..." << endl;
_getch();
cout << "Something" << endl;

.

821530cookie-checkWie simulieren Sie “Drücken Sie eine beliebige Taste, um fortzufahren?”

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy