 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Tarik Mustafic Guest
|
Posted: Mon Jul 31, 2006 2:58 am Post subject: string parsen mit strtok |
|
|
Hallo allerseits,
ich bin ein Java->C++ Quereinsteiger Ich wollte mal einen String
parsen, und die Teilstrings einfach mal abspeichern und später einzeln
ausgeben.
Habe im Netz nach Tokenizer (wie in Java ) gesucht, und bin auf die
Funktion "strtok" gestossen. Ich wollte dann ein Beispiel mir angucken
und fand folgendes im Netz:
1) int i = 1;
2) char String[] = "Hallo;du,schöne#Welt";
3)
4) char* pToken = strtok(String, ";,#");
5) if (pToken)
6) {
7) printf("Token%d: %s\n", i,pToken);
i++;
9) while ( (pToken = strtok(NULL, ";,#")) )
10) {
11) printf("Token%d: %s\n", i,pToken);
12) i++;
13) }
14) }
Mir ist die Vorgehensweise von strtok nicht klar, vorallem folgende Zeilen:
4) in dieser Zeile wird doch der Zeiger gesetzt oder? Also auf den
ersten Buchstaben des Strings?
5) if-Abfrage auf Zeiger? was wird hier geprüft?
9) was macht passiert bei (pToken = strtok(NULL, ";,#")? wird hier zum
nächsten trennzeichen gegangen? Wieso steht NULL im strtok-aufruf
verwendet,wie ist das zu lesen?
Würde mich sehr freuen wenn mir jemand das zeug kurz erklären könnte
oder wenigstens eine gut erklärte seite empfehlen könnte, wo ich
nachlesen und mit dem zeug weiterarbeiten kann.
bedanke mich im voraus.
MfG
Tarik |
|
| Back to top |
|
 |
albrecht.fritzsche Guest
|
Posted: Sat Aug 05, 2006 1:21 pm Post subject: Re: string parsen mit strtok |
|
|
Tarik Mustafic wrote:
| Quote: | Hallo allerseits,
ich bin ein Java->C++ Quereinsteiger Ich wollte mal einen String
parsen, und die Teilstrings einfach mal abspeichern und später einzeln
ausgeben.
Habe im Netz nach Tokenizer (wie in Java ) gesucht, und bin auf die
Funktion "strtok" gestossen.
|
Oh je strtok() ist eine der grauenvollsten C (oder POSIX?)
Library-Funktionen und sollte, wenn möglich, vermieden
werden. (Leider habe ich Gruende dafür nicht mehr parat - IIRC
gibt's da Bugs zumindest auf Linux in multi-threaded Code auf
Grund statischer Daten).
C++ bietet Dir ja std::string (nun ja, auch kein Ruhmesblatt von
Interface) an, inkl unzähliger Funktionen wie
std::string::find_first_of()
oder auch stand-alone Funktionen wie
std::find_first_of()
Damit kann man ein Parsen in C++ leicht und sicher implementieren,
ohne auf "no-goes" wie strtok() zurueckgreifen zu müssen.
Ali |
|
| Back to top |
|
 |
Stefan Reuther Guest
|
Posted: Sat Aug 05, 2006 2:26 pm Post subject: Re: string parsen mit strtok |
|
|
Tarik Mustafic wrote:
| Quote: | 1) int i = 1;
2) char String[] = "Hallo;du,schöne#Welt";
3)
4) char* pToken = strtok(String, ";,#");
5) if (pToken)
6) {
7) printf("Token%d: %s\n", i,pToken);
i++;
9) while ( (pToken = strtok(NULL, ";,#")) )
10) {
11) printf("Token%d: %s\n", i,pToken);
12) i++;
13) }
14) }
Mir ist die Vorgehensweise von strtok nicht klar, vorallem folgende Zeilen:
|
Erstmal als Warnung: strtok ist böse. Warum kommt später.
| Quote: | 4) in dieser Zeile wird doch der Zeiger gesetzt oder? Also auf den
ersten Buchstaben des Strings?
|
Auf das erste Token, das strtok aus dem 'String' rausgefummelt hat.
| Quote: | 5) if-Abfrage auf Zeiger? was wird hier geprüft?
|
Ob strtok ein Token gefunden hat. Wenn das nicht der Fall ist, kommt ein
Null-Zeiger zurück. Während Java in if, while usw. immer nur boolesche
Werte akzeptiert, setzt C++ immer automatisch je nach Typ ein '!= 0',
'!= 0.0', '!= null' dazu. Die Zeile wäre in Java 'if (pToken != null)'.
| Quote: | 9) was macht passiert bei (pToken = strtok(NULL, ";,#")? wird hier zum
nächsten trennzeichen gegangen? Wieso steht NULL im strtok-aufruf
verwendet,wie ist das zu lesen?
|
NULL heißt in diesem Fall, dass strtok dir das nächste Token aus dem mit
dem vorigen strtok verarbeiteten 'String' geben soll. strtok merkt den
sich intern.
Das, was du da oben geschrieben hast, ist aber C. Es ist auch als C++
übersetzbar, aber kein guter Stil.
- es verwendet char[] und char* statt std::string. Das ist ungefähr das
gleiche, das es auch in Java wäre (char[] statt java.lang.String).
'char*' ist etwas, das es in Java nicht gibt.
- strtok modifiziert den Eingabestring.
- strtok ist weder reentrant, noch thread-safe. Du kannst also immer
nur einen String auf einmal zerlegen.
for (p = strtok(text, ","); p != 0; p = strtok(NULL, ","))
for (q = strtok(p, "="); q != 0; q = strtok(NULL, "="))
/* ... */
um einen String der Form "a=b=c,d=e,f=g=h" zu zerlegen geht also
nicht.
In C++ verwendet man normalerweise std::string. Dort solltest du dir
insbesondere die Funktionen 'find_first_of' und 'find_first_not_of'
anschauen. Den Tokenizer musst du dir dann allerdings leider selber
bauen. Eine Möglichkeit wäre zum Beispiel:
std::string s = "Hallo;du,schöne#Welt";
std::string::size_type p, q;
q = 0;
while (1) {
p = s.find_first_of(";,#", q);
std::cout << s.substr(q, p-q) << std::endl;
if (p == s.npos)
break;
q = p+1;
}
(verhält sich ein klein wenig anders als das strtok-Beispiel bei
Vorhandensein einer Folge von mehreren Trennzeichen.)
Stefan |
|
| Back to top |
|
 |
Klaus Schroeder Guest
|
Posted: Sat Aug 05, 2006 2:48 pm Post subject: Re: string parsen mit strtok |
|
|
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Tarik Mustafic schrieb:
| Quote: | Hallo allerseits,
ich bin ein Java->C++ Quereinsteiger Ich wollte mal einen String
parsen, und die Teilstrings einfach mal abspeichern und später einzeln
ausgeben.
Habe im Netz nach Tokenizer (wie in Java ) gesucht, und bin auf die
Funktion "strtok" gestossen. Ich wollte dann ein Beispiel mir angucken
und fand folgendes im Netz:
1) int i = 1;
2) char String[] = "Hallo;du,schöne#Welt";
3)
4) char* pToken = strtok(String, ";,#");
5) if (pToken)
6) {
7) printf("Token%d: %s\n", i,pToken);
i++;
9) while ( (pToken = strtok(NULL, ";,#")) )
10) {
11) printf("Token%d: %s\n", i,pToken);
12) i++;
13) }
14) }
Mir ist die Vorgehensweise von strtok nicht klar, vorallem folgende Zeilen:
4) in dieser Zeile wird doch der Zeiger gesetzt oder? Also auf den
ersten Buchstaben des Strings?
|
Ja, auf das erste Zeichen des 1. Tokens, soweit der Aufruf erfolgreich
war. Dabei muss man wissen, dass das erste Zeichen hinter dem
gelieferten Token mit '\0' überschrieben wird!!! D.H. der
Ursprungs-String (in diesem Fall String) wird durch Aufruf dieser
Funktion wirklich verändert!
| Quote: | 5) if-Abfrage auf Zeiger? was wird hier geprüft?
|
if (pToken)
ist dasselbe wie
if (pToken != NULL)
strtok() liefert nämlich NULL, wenn kein Token (mehr) gefunden wurde;
beim ersten Aufruf kann das eigentlich nur dadurch passieren, dass der
Originalstring leer ist oder nur aus Trennzeichen (2. Argument) besteht.
| Quote: | 9) was macht passiert bei (pToken = strtok(NULL, ";,#")? wird hier zum
nächsten trennzeichen gegangen? Wieso steht NULL im strtok-aufruf
verwendet,wie ist das zu lesen?
|
strtok() löst die Aufgabe, nicht nur das erste Token, sondern auch alle
weiteren zu finden. Beim ersten Aufruf muss als 1. Argument die
Anfangsadresse des zu durchsuchenden Strings übergeben werden, bei jedem
weiteren Aufruf, der weitere Tokens liefern soll, muss NULL als 1.
Argument übergeben werden. M.a.W. wenn strtok() im 1. Parameter NULL
vorfindet, weiß es, dass es in demjenigen String weitersuchen soll,
indem es schon beim vorherigen Aufruf gesucht hat. strtok() merkt sich
bei jedem Aufruf (mit einem static-char-Pointer) die Position, an der es
beim nächsten Aufruf weitersuchen muss.
MfG
Klaus
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)
Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org
iD8DBQFE1Gl/FiIwKQhNwYMRArWZAKC0TOQFMtUMeqYTOwB15CtswyftugCg7q6S
vwEnmSj9y4WrZ5gxrbYCOAE=
=xtGe
-----END PGP SIGNATURE----- |
|
| Back to top |
|
 |
Rolf Magnus Guest
|
Posted: Sat Aug 05, 2006 6:22 pm Post subject: Re: string parsen mit strtok |
|
|
albrecht.fritzsche wrote:
| Quote: | Tarik Mustafic wrote:
Hallo allerseits,
ich bin ein Java->C++ Quereinsteiger Ich wollte mal einen String
parsen, und die Teilstrings einfach mal abspeichern und später einzeln
ausgeben.
Habe im Netz nach Tokenizer (wie in Java ) gesucht, und bin auf die
Funktion "strtok" gestossen.
Oh je strtok() ist eine der grauenvollsten C (oder POSIX?)
|
ISO C.
| Quote: | Library-Funktionen und sollte, wenn möglich, vermieden
werden. (Leider habe ich Gruende dafür nicht mehr parat - IIRC
gibt's da Bugs zumindest auf Linux in multi-threaded Code auf
Grund statischer Daten).
|
Das ist eigentlich kein Bug, sondern eher ein Design-Problem der Funktion
selbst. Der statische Puffer ist unvermeidbar.
Ei nweiterer wesentlicher Grund ist, daß strok den zu parsenden String
verändert, worauf man natürlich achten muß, wenn man ihn noch braucht.
Außerdem darf man es dadurch natürlich auch nicht mit konstanten Strings
verwenden. Wenn man mehrere Delimeter-Zeichen angibt, kann man nach dem
Parsen nicht mehr erkennen, welcher zu einer bestimmten Trennung geführt
hat. |
|
| Back to top |
|
 |
Torsten Landschoff Guest
|
Posted: Sat Aug 05, 2006 6:27 pm Post subject: Re: string parsen mit strtok |
|
|
Hi Tarik,
Tarik Mustafic schrieb:
| Quote: | ich bin ein Java->C++ Quereinsteiger Ich wollte mal einen String
parsen, und die Teilstrings einfach mal abspeichern und später einzeln
ausgeben.
|
Soweit kein Problem.
| Quote: | Habe im Netz nach Tokenizer (wie in Java ) gesucht, und bin auf die
Funktion "strtok" gestossen. Ich wollte dann ein Beispiel mir angucken
und fand folgendes im Netz:
1) int i = 1;
2) char String[] = "Hallo;du,schöne#Welt";
3)
4) char* pToken = strtok(String, ";,#");
5) if (pToken)
6) {
7) printf("Token%d: %s\n", i,pToken);
i++;
9) while ( (pToken = strtok(NULL, ";,#")) )
10) {
11) printf("Token%d: %s\n", i,pToken);
12) i++;
13) }
14) }
Mir ist die Vorgehensweise von strtok nicht klar, vorallem folgende Zeilen:
4) in dieser Zeile wird doch der Zeiger gesetzt oder? Also auf den
ersten Buchstaben des Strings?
|
Ja. Durch den Aufruf von strtok mit erstem Parameter != 0 wird
ausserdem als Seiteneffekt der Standardbibliothek mitgeteilt, welcher
String tokenisiert werden soll. Wenn Du mehrere Threads hast, geht
sowas natürlich sofort baden (oder wenn Du zwischendrin noch anderen
Routinen aufrufst, die strtok verwenden).
Zusätzlich wird nach dem ersten Trennzeichen gesucht und selbiges
durch ein '\0' ersetzt, was in C(++) das Ende eines Strings
kennzeichnet. Dabei wird der Originale String ZERSTÖRT!
| Quote: | 5) if-Abfrage auf Zeiger? was wird hier geprüft?
|
Entspricht einer Prüfung pToken != null in Java. strtok liefert 0,
wenn das Ende des Strings erreicht wird (und keine weiteren Token mehr
zu finden sind).
| Quote: | 9) was macht passiert bei (pToken = strtok(NULL, ";,#")? wird hier zum
nächsten trennzeichen gegangen? Wieso steht NULL im strtok-aufruf
verwendet,wie ist das zu lesen?
|
Der erste Parameter NULL sagt strtok, dass Du das nächste Token aus
dem angefangenen String haben willst. Fiese Sache, die statischen
Variablen, die dahinter stehen...
| Quote: | Würde mich sehr freuen wenn mir jemand das zeug kurz erklären könnte
oder wenigstens eine gut erklärte seite empfehlen könnte, wo ich
nachlesen und mit dem zeug weiterarbeiten kann.
|
Willst Du das wirklich? Du könntest eher an der Tokenizer-Bibliothek
von boost interessiert sein, frei verfügbar und dokumentiert unter
http://www.boost.org/libs/tokenizer
HTH
Torsten |
|
| Back to top |
|
 |
Torsten Landschoff Guest
|
Posted: Sat Aug 05, 2006 6:29 pm Post subject: Re: string parsen mit strtok |
|
|
Hi Albrecht,
albrecht.fritzsche schrieb:
| Quote: | Tarik Mustafic wrote:
Oh je strtok() ist eine der grauenvollsten C (oder POSIX?)
Library-Funktionen und sollte, wenn möglich, vermieden
werden. (Leider habe ich Gruende dafür nicht mehr parat - IIRC
gibt's da Bugs zumindest auf Linux in multi-threaded Code auf
Grund statischer Daten).
|
Broken by design, siehe meine andere Email. Das fiese an strtok sind
folgende Seiteneffekte:
a) der zu untersuchende String wird zerstört
b) die Library merkt sich in einer statischen Variable, welcher String
bearbeitet wird
Beides ziemlich unschön, wobei man mit beiden leben kann, wenn man die
Konsequenzen im Hinterkopf hat. Ärgerlich nur, dass von strtok zwar
abgeraten wird, aber der ISO C++ Standard keine Alternative zu bieten
hat (
Gruß, Torsten |
|
| Back to top |
|
 |
Tibor Pausz Guest
|
Posted: Sun Aug 06, 2006 8:32 pm Post subject: Re: string parsen mit strtok |
|
|
Torsten Landschoff <t.landschoff (AT) gmx (DOT) de> wrote:
| Quote: | Ärgerlich nur, dass von strtok zwar abgeraten wird, aber der ISO C++
Standard keine Alternative zu bieten hat (
|
Boost bietet Lösungen für die meisten Probleme, unter anderem einem
Tokenizer und einen Parsergenerator bzw. man kann ANTLR benutzen. Es
kommt halt drauf an, was man wirklich benötigt. |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|