2012-04-13 9 views
3

Code:ANSI C - wie liest man von stdin Wort für Wort?

#include <stdio.h> 
int main(void) { 
    char i[50]; 
    while(scanf("%s ", i)){ 
     printf("You've written: %s \n", i); 
    } 
    printf("you have finished writing\n"); 

    return 0; 
} 

Ein Problem ist, dass der Code nicht tun, wie es zu erwarten ist. Wenn ich in getippt:

abc def ghi. 

Es wäre Ausgabe:

You've written: abc 
You've written: def 

Wie kann ich es beheben? Das Ziel ist es, jedes einzelne Wort von stdin zu lesen, bis es "ENTER" oder ein "." (Punkt).

+0

Was über das Schreiben 'scanf ("% s ")' einmal, dann Aufruf von 'scanf ("% s ")' in der Schleife? –

+0

Abgesehen von dem Problem, benutzen Sie bitte 'scanf ("% 49s ", i)' in diesem Fall, um die Pufferüberläufe zu verhindern. "K? – dmckee

+0

Danke, aber sie haben das Problem nicht behoben. Die Sache ist, dass die while-Schleife endet, bevor die letzte Gruppe von Charakteren erreicht wird, und das ist nicht das, was sie tun soll. –

Antwort

5

@cnicutar ist ziemlich nah, aber Sie wollen anscheinend nur etwas anderes als whitespace lesen, und wollen aufhören, ein einzelnes Wort zu lesen, wenn Sie whitespace bekommen, also für Sie scanset, wollen Sie wahrscheinlich etwas mehr wie:

while(scanf(" %49[^ \t.\n]%*c", i)) { 

Dabei springt der Anfang Raum über jeden Leerraum. Das Scan-Set liest dann bis es ein Leerzeichen, einen Tab, eine neue Zeile oder einen Punkt erreicht. Das% * c liest dann das nächste Zeichen aus (aber verwirft es) (normalerweise dasjenige, das den Scan gestoppt hat).

Dies kann jedoch ein Zeichen wegwerfen, wenn/wenn Sie das Ende des Puffers erreichen, also möchten Sie% c verwenden und stattdessen ein Zeichen zum Einlesen bereitstellen. Dadurch können Sie sich von einem einzelnen Wort erholen, das länger ist als der von Ihnen bereitgestellte Puffer.

+0

Ich mag den '% * c' Trick :-) – cnicutar

-1

Der einfachste Weg, dies zu tun ist mit flex. Ansonsten wiederholst du eine Menge schwieriger, komplexer Arbeit und wirst wahrscheinlich Fehler machen.

Lesen Sie auch lex and yacc, 2nd edition.

+3

Nun - nicht wirklich. –

+2

Möglich? Bestimmt. Am einfachsten? Vielleicht nicht. – dmckee

+1

Für dieses spezielle Problem, das ist so ähnlich wie mit einem Presslufthammer einen Bilderhaken zu hängen. –

4

Wie wäre:

scanf("%49[ ^\n.]", str) 

Oder so ähnlich.

+0

Das bricht nicht wirklich * spaces *, oder? – dmckee

+0

Nur zu meiner Information ... was bedeutet "% 49 [^ \ n.]"? Ist es ein regelmäßiger Ausdruck oder so etwas? Danke! – nay

+0

@dmckee Es tut es nicht. Ich hatte den Eindruck, der Op möchte die ganze Zeile lesen. Jerry Coffin hat eine bessere Antwort. – cnicutar

1

Ditch scanf zusammen und gehen mit fgets:

while (fgets(i, sizeof i, stdin)) 
{ 
    printf("you've written: %s\n", i); 
} 

mit folgenden Einschränkungen:

  1. Wenn Raum im Zielpuffer gibt es, fgets wird das hintere Newline als Teil der Eingabe speichern ;

  2. Wenn Sie ein . auf der Suche nach dem Lesen aufhören wollen, dann müssen Sie eine gewisse Logik hinzufügen, um es in der Eingabezeichenfolge zu suchen, wie die folgenden:


    int foundDot = 0; 
    while (fgets(i, sizeof i, stdin) && !foundDot) 
    { 
     char *dot = strchr(i, '.'); 
     char *newline = strchr(i, '\n'); 

     if (dot != NULL) 
     { 
     foundDot = 1; 
     *dot = 0; // overwrite the '.' character with the 0 terminator 
     } 

     if (newline != NULL) 
     { 
     *newline = 0; // overwrite newline character with 0 terminator 
     } 

     /** 
     * Assuming you don't want to print a blank line if you find a dot 
     * all by itself. 
     */ 
     if (strlen(i) > 0) 
     printf("you've written: %s\n", i); 
    }
Verwandte Themen