2009-07-12 8 views
1

Lassen Sie uns sagen, dass ich eine Liste von Elementen aus der Standardeingabe erwarten, die kaufen Kommas getrennt sind, wie folgt aus:Kann scanf ein Formatzeichen innerhalb einer Zeichenkette identifizieren?

item1, item2, item3,...,itemn 

und ich möchte auch den Benutzer ermöglichen, Weißräume zwischen den einzelnen Posten und Komma zu emittieren, so diese Art der Eingabe ist in meinem Programm legal:

item1,item2,item3,...,itemn 

Wenn ich scanf wie folgt verwenden:

scanf("%s,%s,%s,%s,...,%s", s1, s2, s3, s4,...,sn); 

es wird scheitern, wenn t Hier sind keine Leerzeichen (ich habe es getestet), weil es sich auf die gesamte Eingabe als eine Zeichenfolge bezieht. Wie kann ich dieses Problem nur mit C-Standard-Bibliotheksfunktionen lösen?

Antwort

7

Sie können sich strtok ansehen. Lesen Sie zuerst die Zeile in einen Puffer, dann tokenize:

const int BUFFERSIZE = 32768; 
char buffer[BUFFERSIZE]; 
fgets(buffer, sizeof(buffer), stdin); 

const char* delimiters = " ,\n"; 
char* p = strtok(buffer, delimiters); 
while (p != NULL) 
{ 
    printf("%s\n", pch); 
    p = strtok(NULL, delimiters); 
} 

jedoch mit strtok Sie kennen die potential issues related to reentrance sein müssen.

+1

Verwenden Sie strtok_r(), um Wiedereintrittsprobleme zu umgehen. Wenn Ihre Plattform nicht über strtok_r() verfügt, gibt es hier eine Public-Domain-Implementierung: http://snipplr.com/view/16918/strtokr/ –

8

Die schnelle Antwort ist, niemals scanf verwenden, um Benutzereingaben zu lesen. Es ist für das Lesen streng formatierter Eingaben von Dateien gedacht und ist selbst dann nicht sehr gut. Zumindest sollten Sie ganze Zeilen lesen und dann mit sscanf() analysieren, was Ihnen eine gewisse Chance gibt, Fehler zu korrigieren. bestenfalls sollten Sie Ihre eigenen Analysefunktionen schreiben

Wenn Sie tatsächlich C++ verwenden, untersuchen Sie die Verwendung der C++ - Zeichenfolge und Stream-Klassen, die viel leistungsfähiger und sicherer sind.

2

Ich denke, es ist besser, dafür eine eigene Parsing-Funktion zu schreiben. Aber wenn Sie scanf trotz seiner Fallstricke immer noch bevorzugen, können Sie eine Workaround machen, ersetzen Sie einfach% s mit% [^, \ t \ r \ n].

Das Problem, dass% s Sequenz von Nicht-Leerzeichen übereinstimmen, so dass es auch Komma schluckt. Wenn Sie also% s durch% [^, \ t \ r \ n] ersetzen, funktioniert es fast genauso (Unterschied ist, dass% s issspace (3) verwendet, um Leerzeichen zu finden. In diesem Fall geben Sie jedoch explizit an, welche Leerzeichen Sie verwenden möchten Übereinstimmung und diese Liste ist wahrscheinlich nicht die selbe wie für isspace).

Hinweis: Wenn Sie Leerzeichen vor und nach dem Komma zulassen möchten, müssen Sie Ihrer Formatzeichenfolge Leerzeichen hinzufügen. Formatierzeichenfolge "% [^, \ t \ r \ n],% [^, \ t \ r \ n]" entspricht Strings wie "Hallo, Welt", "Hallo, Welt", "Hallo, Welt".

+1

Äh, ich glaube nicht, dass Reguläre Ausdrücke in 'scanf' funktionieren. – GManNickG

+1

@GMan: Haben Sie überprüft, dass es nicht funktioniert? Es funktioniert hier. –

+0

Oder überprüfen Sie Ihren K & R. – caf

Verwandte Themen