Warum muss ich zweimal Strg-D eingeben, um das Dateiende zu markieren?

Lesezeit: 5 Minuten

Benutzer-Avatar
mualloc

char **query; 
query = (char**) malloc ( sizeof(char*) );

int f=0;
int i=0,j=0,c;


while((c=getchar())!=EOF)
{      
    if(!isalpha(c))
        continue;

    if(f==1)
        query=(char**) realloc(query,(i+1)*sizeof(char*));

    query[i]=(char*) malloc(sizeof(char));
    query[i][j]=c;
    j++;


    while( (c=getchar())!=EOF&&c!=' '&&c!='\t' )
    {      

        query[i]=(char*) realloc(query[i],(j+1)*sizeof(char));

        query[i][j]=c;
        ++j;
    }   

    query[i][j]='\0';
    printf("%s\n",query[i]);
    if(c==EOF){

        break;
    }   

   ++i;
   f=1;
   j=0;
}

Ich möchte, dass das obige Code-Snippet eine Zeile von Zeichenfolgen liest, die durch Leerzeichen und Tabulatoren bis zu EINEM EOF getrennt sind, aber es erfordert 2 EOFs, um die Schleife zu beenden. Außerdem können Zeichenfolgen nur aus alphabetischen Zeichen bestehen.

Ich kämpfe an ungefähr 2 Tagen. Bitte geben Sie ein Feedback.

BEARBEITEN: Höchstwahrscheinlich ist der Grund, dass ich die Tasten STRG + D gedrückt habe, nachdem ich die letzte Zeichenfolge geschrieben habe, nicht die Eingabetaste, aber jetzt drücke ich die Eingabetaste und dann STRG + D, es funktioniert wie erwartet. Aber wie kann ich es so ändern, dass es beendet wird, nachdem ich nach der letzten Zeichenfolge einmal STRG + D gedrückt habe?

  • Es sind keine zwei EOFs erforderlich, um die Schleife zu beenden. Es erfordert nur einen. Innerhalb der Schleife gibt es, wenn sie festgestellt hat, dass sie das EOF noch nicht gesehen hat, eine innere Schleife, die mit dem Scannen der Eingabe fortfährt. Diese innere Schleife stoppt auch bei EOF (nur einer) und den folgenden if(c==EOF) wird aus der Schleife ausbrechen, wenn dieser eine EOF angetroffen wurde.

    – Schleicher

    21. Januar 2014 um 14:24 Uhr

  • sizeof(char) ist immer eins. Und werfen Sie nicht den Rückgabewert von malloc().

    Benutzer529758

    21. Januar 2014 um 14:25 Uhr

  • H2CO3 Ich denke, sizeof(char)=1 ist fehlerhaft und wenn der Rückgabewert von malloc nicht gecastet wird, gibt es void zurück.

    – dualloc

    21. Januar 2014 um 14:46 Uhr


  • sizeof(char)==1 ist durch die Sprache absolut gewährleistet. Wenn Sie das Ergebnis nicht werfen malloc()das void* Ergebnis wird implizit in den Zieltyp der Zuweisung konvertiert.

    – Keith Thompson

    21. Januar 2014 um 15:06 Uhr

Benutzer-Avatar
Keith Thompson

Auf Unix-ähnlichen Systemen (zumindest standardmäßig) wird eine End-of-File-Bedingung durch die Eingabe ausgelöst Strg-D am Anfang einer Zeile oder indem Sie Strg-D eingeben zweimal wenn Sie nicht am Anfang einer Zeile stehen.

Im letzteren Fall hat die letzte gelesene Zeile kein a '\n' am Ende davon; das musst du eventuell zulassen.

Dies wird (eher indirekt) von POSIX / The Open Group Base Specifications Issue 7, in spezifiziert Abschnitt 11insbesondere 11.1.9:

EOF
Sonderzeichen bei der Eingabe, das erkannt wird, wenn das ICANON-Flag gesetzt ist. Beim Empfang werden alle zu lesenden Bytes sofort an den Prozess übergeben, ohne auf ein zu warten, und das EOF wird verworfen. Wenn also keine Bytes warten (das heißt, das EOF trat am Anfang einer Zeile auf), soll eine Byte-Zählung von Null von read() zurückgegeben werden, was eine Dateiende-Anzeige darstellt. Wenn ICANON gesetzt ist, wird das EOF-Zeichen bei der Verarbeitung verworfen.

Die POSIX read() Die Funktion zeigt ihrem Aufrufer eine Dateiende- (oder Fehler-) Bedingung an, indem sie eine Byteanzahl von Null zurückgibt, was anzeigt, dass keine Datenbytes mehr zu lesen sind. (Cs <stdio> ist auf POSIX-Systemen darauf aufgebaut read() und andere POSIX-spezifische Funktionen.)

EOF (nicht zu verwechseln mit C EOF Makro) ist standardmäßig zugeordnet Strg-D. Die Eingabe des EOF-Zeichens am Anfang einer Zeile (entweder ganz am Anfang der Eingabe oder unmittelbar nach einem Zeilenumbruch) löst eine sofortige Dateiende-Bedingung aus. Wenn Sie das EOF-Zeichen anders als am Anfang einer Zeile eingeben, werden die vorherigen Daten in dieser Zeile sofort von der nächsten zurückgegeben read() Aufruf, der nach genügend Bytes fragt; Eingabe des EOF-Zeichens wieder macht dasselbe, aber in diesem Fall gibt es keine verbleibenden Bytes zum Lesen und es wird eine Dateiende-Bedingung ausgelöst. Ein einzelnes EOF-Zeichen in der Mitte einer Zeile wird verworfen (if ICANON eingestellt ist, was normalerweise der Fall ist).

  • Können Sie bitte einen Verweis auf Ihre Antwort angeben?

    – dualloc

    21. Januar 2014 um 15:06 Uhr


  • Ich konnte keine Referenz dafür finden (ich werde später noch einmal nachsehen). Aber du kannst es selbst versuchen. Geben Sie an einem Shell-Prompt ein wcdann tippen abc gefolgt von der zweimaligen Eingabe von Strg-D. Die Ausgabe sollte sein abc 0 1 3was darauf hindeutet wc sah 3 Zeichen, davon 0 Zeilenumbrüche.

    – Keith Thompson

    21. Januar 2014 um 15:16 Uhr

  • @nos: Ich bin mir sicher, dass es irgendwo dokumentiert ist.

    – Keith Thompson

    21. Januar 2014 um 15:17 Uhr

  • @mualloc: Ich habe meine Antwort aktualisiert, um zu erklären (versuchen), wie POSIX impliziert, dass Sie Strg-Ds benötigen. Was die Ablehnung betrifft, kann ich es nicht erklären (ich habe Ihre Frage nicht selbst abgelehnt, und Ablehnungen sind von Natur aus anonym), aber Ihre Frage, wie sie derzeit geschrieben ist, ist etwas unklar. Ich werde den Titel gleich aktualisieren; Bitte überprüfen Sie, ob es immer noch das widerspiegelt, was Sie fragen.

    – Keith Thompson

    29. Januar 2014 um 16:27 Uhr

  • @mualloc: Die Ablehnung Ihrer Frage ist immer noch da. Ich habe dafür gestimmt. (Sie verlieren 1 Wiederholungspunkt für jede negative Bewertung, gewinnen 5 für jede positive Bewertung einer Frage und gewinnen 10 für jede positive Bewertung einer Antwort; Ihre Frage hat derzeit eine Nettopunktzahl von 0, für die Sie netto 4 Wiederholungspunkte erhalten haben.)

    – Keith Thompson

    29. Januar 2014 um 16:56 Uhr

Benutzer-Avatar
tlochner95

Für den unwahrscheinlichen Fall, dass jemand dies sieht, der die Hilfe braucht, die ich brauche … Ich habe gesucht und versucht herauszufinden, warum ich dieses seltsame Verhalten mit meinem while(scanf) bekomme. Nun, es stellte sich heraus, dass ich hatte while (scanf("%s\n", string) > 0). Der von mir verwendete Editor (Atom) fügt automatisch ein “\n” in meinen Scan ein, ohne dass ich es bemerke. Das hat mich Stunden gekostet, und zum Glück hat mich jemand darauf hingewiesen.

Die Return-Taste erzeugt kein EOF, deshalb die Bedingung getchar() != EOF erkennt es nicht. Sie können dies tun, indem Sie drücken STRG+Z unter Windows bzw STRG+D unter Unix.

  • Wenn Sie auf Ubuntu sind, kümmern Sie sich nicht um Control-Z; das wird nur Ihr Programm unterbrechen.

    – Keith Thompson

    21. Januar 2014 um 15:01 Uhr

1180080cookie-checkWarum muss ich zweimal Strg-D eingeben, um das Dateiende zu markieren?

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

Privacy policy