Nicht Blockierende Charakter Bekommen
- Plattform: Linux 3.2.0 x86 (Debian 7)
- Compiler: GCC 4.7.2 (Debian 4.7.2-5)
Schreibe ich eine Funktion, liest ein einzelnes Zeichen von der Standardeingabe, wenn ein Charakter bereits in stdin. Wenn stdin ist leer, die Funktion wird angenommen, nichts zu tun und -1 zurückgeben. Ich gegoogelt nonblocking-Eingang und auf die verwiesen wurde, poll() oder wählen Sie(). Zuerst habe ich versucht zu verwenden, wählen Sie (), aber ich konnte nicht bekommen es zu arbeiten, also versuchte ich, poll() und kamen zu dem gleichen Schluss. Ich bin nicht sicher, was diese Funktionen tun genau das, aber von dem, was ich verstehe, von poll()'s-Dokumentation, wenn ich rufe es so auf:
struct pollfd pollfds;
pollfds = STDIN_FILENO;
pollfds.events = POLLIN;
poll(pollfds, 1, 0);
wenn(pollfds.revents & POLLIN) wird wahr, wenn "andere Daten als high-priority-Daten können gelesen werden ohne zu blockieren.". Aber poll() immer mal in meiner test-situation. Wie Teste ich die Funktion könnte das problem sein, aber die Funktionalität, die ich will, ist genau das, was ich am testen für. Hier ist die Funktion aktuell und der test-situation als gut.
#include <poll.h>
#include <stdio.h>
#include <unistd.h>
int ngetc(char *c)
{
struct pollfd pollfds;
pollfds.fd = STDIN_FILENO;
pollfds.events = POLLIN;
poll(&pollfds, 1, 0);
if(pollfds.revents & POLLIN)
{
//Bonus points to the persons that can tell me if
//read() will change the value of '*c' if an error
//occurs during the read
read(STDIN_FILENO, c, 1);
return 0;
}
else return -1;
}
//Test Situation:
//Try to read a character left in stdin by an fgets() call
int main()
{
int ret = 0;
char c = 0;
char str[256];
//Make sure to enter more than 2 characters so that the excess
//is left in stdin by fgets()
fgets(str, 2, stdin);
ret = ngetc(&c);
printf("ret = %i\nc = %c\n", ret, c);
return 0;
}
- stackoverflow.com/questions/3962263/...
- Ihre Funktion niemals 0 zurückgeben : if ( ... ) return errno; else return EWOULDBLOCK; ; gut, was ist der Einsatz für die letzten zurück ?
- wenn ein Fehler Auftritt, während Sie das Lesen, wird die Funktion return errno aber wenn ein Fehler nicht auftreten, während der Lektüre die Funktion 0 zurück. Die Anweisung beginnt mit der überprüfung, um zu sehen, ob Daten in der Standardeingabe, wenn keine Daten die Anweisung Kurzschlüsse, bevor read() wird aufgerufen, aber wenn es Daten in der Standardeingabe read() wird aufgerufen, und wenn read() liefert eine -1, dann ein read error occured also return errno ansonsten, wenn keine lese-Fehler tritt auf, dann ist die Bedingung false, so wird 0 zurückgegeben.
- ich meinte : es sieht aus wie das Letzte return 0 wird nur ein unreachable code durch if () return A; else return B; Muster.
- Oh ja, ich weiß, was du meinst, es sieht ein wenig umständlich
Du musst angemeldet sein, um einen Kommentar abzugeben.
Du tust IO falsch, die POSIX-Handbuch und alle anderen zugehörigen Dokumentation ausdrücklich sagt, dass Sie nie zu mischen IO erfolgt auf
FILE *
s und Datei-Deskriptoren. Sie haben sehr eklatant gebrochen von dieser Regel. Diese Regel ist in Ort, weilFILE *
s verwenden Pufferung ein dies bedeutet, dass nach einem Aufruffgets
es wird nichts mehr übrig fürread
zu bekommen, weilfgets
schon gelesen alle ausstehenden Daten in einem Puffer gehalten, die in denFILE *
Struktur.So, da es keine Möglichkeit gibt zu prüfen, ob eine ISO-C-IO-Methode blockiert, wir haben die Verwendung von Datei-Deskriptoren, nur.
Da wir wissen, dass
STDIN_FILENO
ist nur die Zahl 0, die wir verwenden können,werden alle
read
s auf Datei-Deskriptor 0, um non-blocking-Modus, wenn Sie möchten, verwenden Sie einen anderen Datei-Deskriptor, so dass Sie verlassen können 0 allein dann verwenden Sie einfachdup
zu duplizieren.Diese Weise können Sie bleiben Weg von
Umfrage
vollständig und implementierenngetc
alsoder noch besser, ein makro
So erhalten Sie eine einfache Implementierung für das, was du bist suchen für.
Edit: Wenn Sie immer noch besorgt über das terminal die Pufferung der Eingabe können Sie immer ändern Sie den terminal-Einstellungen finden Sie unter Zum deaktivieren der Zeile Pufferung der Eingabe im xterm aus dem Programm? für weitere Informationen, wie dies zu tun.
Edit: Dem Grund, dass könnte man nicht verwenden
fgetc
stattread
ist aus dem gleichen Grund, dass die Verwendungfgets
wird nicht funktionieren. Wenn einer derFILE *
IO-Funktionen ausgeführt wird, liest es die Daten aus der zugehörigen Datei-Deskriptor. Aber wenn das einmal passiert,poll
wird nie zurückkehren, denn es wartet auf einen Datei-Deskriptor, der ist immer leer, und das gleiche wird passieren mitread
. Also, ich schlage vor, dass Sie der Empfehlung Folgen, die Dokumentation und nie mix streams (IO mitfgets
,fgetc
usw.) und Datei-Deskriptoren (IO mitread
,write
usw.)stdin
war Hintergrundmusik in ein EOF zu erwarten. Nutzt man so etwas wieif (ngetc(c) == -1) Handle_EOF_or_IOError();
if (ngetc (&c) == 0) handle_EOF ();
weilread
zurück0
aufEOF
aber würden Sieif (ngetc (&c) < 0) handle_other_error ();
zu prüfen, für jede andere Art von Fehler.fgets
in der Weise, dass, die Sie angegeben haben. Der ISO-C-standard nicht geben Ihnen einen Weg, es zu tun und mit dem POSIX-standard zu umgehen, müssen Sie über Datei-Deskriptoren, statt.Gibt es zwei Probleme in deinem code.
Laut Handbuch von
poll
zuweisen 0 bis timeout zurück sofortfgets
nicht tut, was Sie erwarten, ist es aus der stdio-Bibliothek und Puffer liest. Angenommen, Sie mindestens 3 Buchstaben eingegeben und die EINGABETASTE drücken, nachfgets
, der Dritte Buchstabe nicht verfügbar sein, umpoll
.So kommentieren Sie die Funktion fgets Zeile, und weisen Sie -1, um die Zeitüberschreitung in
poll
, und führen Sie Sie erneut, um zu sehen, ob das, was Sie wollen.Habe ich nicht erhalten das erwartete Verhalten mit der Antwort oben, und ich hatte wirklich zu berücksichtigen diese Antwort sowie
das festlegen der TTY-in nicht-kanonischen Modus.