2016-02-11 12 views
14

Ist es erlaubt scanf(" ") ohne zusätzliche Argumente zu verwenden, um anfängliche Leerzeichen zu ignorieren?
Ich verwende getchar(), um die Zeichen eines Wortes zu lesen, und ich möchte die Leerzeichen vor dem Wort ignorieren (Leerzeichen nach werden verwendet, um das Ende des Wortes zu überprüfen).
Der Code ist der folgende, ist es richtig?scanf ohne zusätzliche Argumente in C

char *read_word() { 
    int size = 2; 
    int char_count = 0; 
    char *s; 
    char ch; 

    s = mem_alloc(size); 

    scanf(" "); 

    while ((ch = getchar()) != EOF) { 
     if (char_count >= size) { 
      s = mem_realloc(s, size++); 
     } 

     if (ch == ' ' || ch == '\n') { 
      s[char_count] = '\0'; 
      break; 
     } 

     s[char_count++] = ch; 
    } 

    return s; 
} 
+6

Absolut ..... – DevSolar

+2

Abgesehen: 'mem_realloc (s, Größe ++);' -> 'mem_realloc (s, ++ size); ' –

+0

Hinweis: Code kann' s' zurückgeben, dem ein Nullzeichen fehlt. – chux

Antwort

13

Aus der Definition der scanf() Funktion (*), Hervorhebung von mir:

Das Format null oder mehr Richtlinien zusammengesetzt ist: ein oder mehr Leerraumzeichen, ein gewöhnliches Multibyte-Zeichen (weder % noch ein Leerzeichen), oder eine Umrechnungsspezifikation.

[...]

Eine Richtlinie besteht aus Leerraumzeichen (s) durch die Eingabe von bis zu dem ersten nicht-white-Leerzeichen Lesen ausgeführt wird (die ungelesene bleibt), oder bis keine Zeichen mehr gelesen werden können.

Also ist perfekt gültig.


(*): ISO/IEC 9899: 1999, 7.19.6.2 Die fscanf Funktion, Abschnitt 3 und 5

Die anderen *scanf Funktionen in Bezug auf diesen Abschnitt definiert sind.

4

würde ich stattdessen versuchen:

int skip = -1; 
if (scanf(" %n", &skip)>=0 && skip>0) { 
    // you have skipped skip spaces 
} 

Die> = 0 Test überprüft, ob scanf nicht scheitern (beispielsweise aufgrund von EOF auf stdin oder Eingabefehler). Der skip>0 Test prüft, ob wir mindestens ein Leerzeichen entfernt haben. Der Konvertierungsspezifizierer %n gibt die Anzahl der analysierten Bytes an.

+0

Der '> = 0'test sieht nicht benötigt aus. Wie hilft es? – chux

+0

Ich dachte, dass 'skip' sich nicht hätte ändern können, wenn EOF auf stdin oder Eingabefehler wäre, also würde' skip' seinen -1-Wert beibehalten und dann den 'skip> 0'-Test nicht bestehen. IAC, den Rückgabewert von 'scanf()' zu überprüfen, ist etwas zu fördern. – chux

+0

Nun, wenn kein Platz übersprungen wurde, schlägt mein Test fehl –

5

Die manpage sagt:

Der Format-String aus einer Folge von Richtlinien

...

Eine Richtlinie ist eine der folgenden besteht:

• Eine Folge von Leerzeichen (Leerzeichen, Tabulatoren, Zeilenumbrüche usw.), siehe Isspace (3)). Diese Direktive passt jede Menge Leerraum, einschließlich keine, in der Eingabe an.

...

so ja, es ist eine legale Verwendung von scanf.


Wenn Sie nach Effizienz sind:

int c; 
while(isspace(c=getchar()) {;} 

nach unten führt einen effizienteren Weg, wie getchar et. al. neigen dazu, _unlocked Gegenstücke zu haben, im Gegensatz zu scanf.

+0

Während in diesem Fall kein Problem war, würde ich vorsichtig sein, sich auf Manpages zu verlassen. Sie unterscheiden normalerweise nicht klar zwischen dem, was ISO C ist, und dem, was POSIX ist - und das * kann * einen Unterschied machen. Wenn also die Frage ist, ob etwas legal ist oder nicht "in C", übertrumpft der Standard die Manpage. (Und ich sage das nicht, nur weil ich es zitiert habe, sondern weil ich von Zeit zu Zeit an und mit Nicht-POSIX-Plattformen arbeite.) – DevSolar

+0

@DevSolar stimme zu. Wir haben ziemlich gleichzeitig gepostet. Ich hätte vielleicht meins nicht gepostet, wenn ich deine zuerst gesehen hätte, aber ich denke, meine hat immer noch einen gewissen Wert (= Ich bekomme Punkte davon: D), also behalte ich es. – PSkocik

+0

Beachten Sie, dass, um Ihr 'getchar'-Beispiel äquivalent zu' scanf ("") 'zu machen, Sie am Ende" ungetc (c, stdin) "eingeben müssen. –

9

zu den anderen Antworten hinzuzufügen, alle folgenden gelten:

scanf(" ");  // skip over whitespace 
scanf("xyz"); // skip over the longest leading substring of "xyz" if present 
       // i.e. "xyz" or "xy" or "x" 
scanf(" %*s "); // skip over the first string and whitespace around it 
+1

schätze, zusätzliches Wissen mit der ursprünglichen Antwort hinzuzufügen - hilfreich –

Verwandte Themen