2009-08-06 7 views
4

Ich verwende die folgende bedingte Anweisung, um von der Standardeingabe zu lesen.read() von stdin ignoriert newline

if ((n = read(0,buf,sizeof(buf))) != 0) 

Wenn Daten von der Standardeingabe eingegeben, in der Regel drückt der Benutzer eingeben, wenn Sie fertig. Aber read() berücksichtigt '\ n' als Eingabe auch in diesem Fall n = 1 und die bedingte wird nicht als falsch ausgewertet. Gibt es eine Möglichkeit, die bedingte Bewertung zu false zu machen, wenn der Benutzer die Eingabe (ohne Eingabe) auf die Standardeingabe drückt, abgesehen von der Überprüfung des Inhalts von buf. Gibt es eine andere Funktion als read(), die ich für diesen Zweck verwenden könnte ??

Was kann eine Möglichkeit sein, das Ende der Eingabe zu bestimmen, wenn die Eingabe von der Standardeingabe (stdin) kommt?

+0

Was wollen Sie tun? Lies jedes Zeichen einzeln? – GManNickG

+0

Nein, wie Sie von der Bedingung sehen können, lese ich von der Standardeingabe in einen Puffer (und sage vielleicht einfach, es auf Standardausgabe zurückzuschreiben). Ich möchte anhalten, wenn der Benutzer nichts eingibt und nur Enter drückt. –

+0

Ah, ich sehe jetzt. Ich habe es falsch gelesen. – GManNickG

Antwort

8

Sie fragen:

Wenn Daten von der Standardeingabe eingegeben, in der Regel der Benutzer drückt, wenn Sie fertig eingeben. Aber lese() berücksichtigt '\ n' auch als Eingabe, in diesem Fall ist n = 1 und die Bedingung wird nicht als falsch ausgewertet.

Der erste Punkt ist sicherlich wahr. Die Eingabetaste entspricht der Newline-Taste. Wenn der Benutzer die Eingabetaste drückt, generiert die Tastatur ein Zeilenumbruchzeichen und die read()-Funktion gibt daher dieses Zeichen zurück. Es ist entscheidend, dass es das tut.

Daher ist Ihre Bedingung fehlgeleitet - eine leere Zeile enthält die Zeilenumbrüche und daher wird die Bytezahl eins sein. Tatsächlich gibt es nur einen Weg, um den read() Aufruf zu bekommen, um 0 zurückzugeben, wenn die Standardeingabe die Tastatur ist, und das ist das 'EOF' Zeichen eingeben - normalerweise control-D auf Unix, control-Z auf DOS. Unter Unix wird dieses Zeichen von dem Terminaltreiber als 'die vorherigen Eingabedaten an das Programm senden, auch wenn noch kein Zeilenumbruch vorhanden ist' interpretiert. Und wenn der Benutzer nichts anderes in die Zeile eingegeben hat, wird die Rückkehr von read() Null sein. Wenn die Eingabe von einer Datei kommt, werden nach dem Lesen der letzten Daten nachfolgende Lesevorgänge 0 Byte zurückgeben.

Wenn die Eingabe von einer Pipe kommt, wird nach dem Lesen aller Daten in der Pipe der Aufruf read() blockiert, bis der letzte Dateideskriptor, der in die Pipe schreiben kann, geschlossen ist; Wenn sich dieser Dateideskriptor im aktuellen Prozess befindet, wird read() für immer hängen bleiben, auch wenn der hängende Prozess nie in der Lage sein wird, den Dateideskriptor write() zu verwenden - vorausgesetzt, es handelt sich um einen single-threaded Prozess.

+0

Kritisch, dass Sie erziehen, warum der Rückgabewert von 0 von read()/recv() sich von einer leeren Zeile unterscheidet. Wenn Sie 0 von read()/recv() erhalten, bedeutet dies, dass Sie sich am Ende aller Eingaben befinden (d. H. Es ist geschlossen, es kann keine neue Eingabe hinzugefügt werden). – Will

+0

NB: Es gibt Geräte, bei denen das Lesen von 'read()' null bedeutet, dass keine weitere Eingabe hinzugefügt werden kann. Meine Antiquitäten zu zeigen - Magnetbandgeräte waren eine solche. Derzeit sind Terminals ein anderer. Mit esoterischen Optionen auf 'open()' (wie O_NONBLOCK) können Sie dieses Verhalten auf anderen Geräten erhalten. Aber eine leere Zeile ist definitionsgemäß eine Zeile, die nur ein Zeilenumbruchzeichen enthält - der Zeilenende-Marker (auch Newline-Zeichen genannt) ist Teil der Daten. Wenn Sie das in Ihrem Programm nicht möchten, müssen Sie es entfernen. Nur 'gets()' entfernt den Zeilenumbruch für Sie, aber Sie sollten ihn * niemals * im Produktionscode verwenden. –

0

Sie besser fgets() für Ihre Aufgabe verwenden (Fang Benutzereingaben), aber auch fgets() speichert Newline-Zeichen im Puffer.

Wenn jedoch Newline vorhanden ist, können Sie sicher sein, dass es sich um das letzte Zeichen in der Zeichenfolge handelt, so dass es leicht zu entfernen ist.

+0

Sie können nicht sicher sein, dass das letzte Zeichen im Puffer ein Zeilenumbruch ist, da fgets() nur den Zeilenumbruch speichert, wenn es einen in der Datei gibt. Kann nicht sein, wenn die letzte Zeile keine enthält. – Inshallah

+0

@Inshalla Ich meinte, wenn Newline im Puffer ist, ist es sicherlich das letzte Zeichen. Ich bearbeite meinen Beitrag, um es explizit zu machen. – qrdl

+0

Zuerst arbeite ich mit Dateideskriptoren hier und nicht Dateizeiger. fgets() übernimmt Dateizeiger. Und was ich tun möchte, ist, das bedingte Ergebnis zu false zu machen, wenn der Benutzer die Eingabetaste drückt. Ich kann natürlich auch hier abwehren, ob Newline als letztes Zeichen eingegeben wurde oder nicht. –

0

Ich bin ziemlich positiv, es gibt keine Möglichkeit, es zu tun, ohne den Puffer Inhalt zu untersuchen. Sogar readline() macht genau das. Warum bist du überhaupt dagegen?

1

Sie müssen den Puffer selbst überprüfen. z.B.

while((n = read(0,buf,sizeof(buf))) > 0) { 
    if(buf[0] == '\n') // won't handle pressing 9 spaces and then enter 
    continue; 
    ... process input 

} 

oder z.B. fgets und abzustreifen nur die \ n

while(fgets(buf,sizeof buf,stdin) != NULL) { 
    char *ptr; 
    size_t len; 

    if((ptr = strchr(buf,'\n')) != NULL) //strip newline 
    *ptr = 0; 
    len = strlen(buf); 
    if(len == 0) 
    continue; 
    ... process input 
} 
2

geben Sie einfach >1 statt !=0

die einzigen Fehlalarme sind einzelne Zeichen Antworten durch einen Interrupt (EOF), gefolgt