Hallo,
Ich habe einen String, den ich mit der C-Funktion strtok_r in
Teilstrings zerlegen will.
In folgendem Beispiel funktioniert das auch wie gewünscht.
1
charstring[50]="wert1,wert2,wert3,wert4,..."
2
char*tmp;
3
char*feld1;
4
char*feld2;
5
char*feld3;
6
...
7
feld1=strtok_r(string,",",&tmp);
8
feld2=strtok_r(NULL,",",&tmp);
9
feld3=strtok_r(NULL,",",&tmp);
10
...
Ergebnis ist feld1 zeitgt auf wert1, usw...
Laut Beschreibung ersetzt die Funktion ja nur alle Trennzeichen durch \0
und gibt bei jedem Aufruf einen Pointer auf den nächsten Stringteil
zurück.
Also sieht der String im Speicher vorher so aus:
wert1,wert2,wert3,...wertn\0
Und nachher:
wert1\0wert2\0wert3\0...wertn\0
| | | |
Die zurückgelieferten Zeiger zeigen dann immer auf die mit |
gekennzeichneten Stellen im Speicher.
Nur wenn jetzt im String ein Wert fehlt, also der String z.B. wir folgt
aussieht:
wert1,,wert3,...wertn\0
Dann ist das Ergebnist nicht mehr das von mir erwartete.
Meine Überlegung war, dass dann feld2 am Schluss auf einen leeren String
'\0' zeigen würde und alle anderen Felder ihren eigentlichen "Inhalt"
hätten.
wert1\0\0wert3\0...wertn\0
| | | |
Leider sind jedoch stattdessen alle Felder um eins verschoben, da der
doppelte Trenner übersprungen wird.
wert1\0\0wert3\0...wertn\0
| | |
Ist das ein Bug, oder gewollt? Wenn gewollt, kennt jemand eine andere
Funktion, die das so erledigt, wie ich es machen will? Sonst muss ichs
halt selbst schreiben.
Compiler ist WinAVR in Version 20070122. Laufen soll das auf nem Mega
32(4).
Gruß Holger
Hallo Namensvetter :)
Ein Bug ist das sicher nicht. Wo kein Teilstring steht
kann man auch kein \0 dranhängen.
Du musst jetzt aber nicht gleich strtok_r()
komplett neu schreiben.
Prüfe deinen String auf ",," Stellen bevor du sie an
strtok_r() übergibst. Füge eine 0 ein wenn du so eine
Stelle findest. ",0,". Das sollte gehen.
Kommen deine Strings aus einem GPS ?
Such dir eine andere Funktion raus:
man strtok_r sagt:
BUGS
Avoid using these functions. If you do use them, note that:
These functions modify their first argument.
These functions cannot be used on constant strings.
The identity of the delimiting character is lost.
The strtok() function uses a static buffer while
parsing, so
it's not thread safe. Use strtok_r() if this matters to
you.
strtok_r frißt auch mehrere direkt aufeinanderfolgende Trennzeichen.
Deshalb ist sie für Strings, in denen Werte fehlen, nicht geeignet.
(Generell sind diese Funktionen nicht nur unsicher, sondern auch von
ziemlich beschränktem Nutzen.)
Ich würde in einer Schleife einen Pointer über den String laufen lassen
und die Zerteilerei zu Fuß machen.
Danke für eure Antworten.
@Werner Hoch: Naja, die Bugs sind nicht wirklich Bugs, sondern eher
Nachteile. Die Spielen bei mir aber alle keine Rolle, da die Funktion an
sich genau das tut, was sie sollt. Bis auf das fressen der doppelten
Trennzeichen.
@holger: Zeichen hinzufügen ist problematisch, der String ist lang. Bis
zu 150 Zeichen oder evt. auch mehr. Das ist schon etwas Aufwand soviel
im Speicher rumzukopieren, wenn ich da jeweils pro Fehlstelle ein
Zeichen anhängen muss. Außer ich könnte das schon in der Leseroutine
machen, da ginge es schneller. Müsste ich mal prüfen.
GPS ist es nicht, aber die Daten sind NMEA ähnlich.
> Ich würde in einer Schleife einen Pointer über den String laufen lassen> und die Zerteilerei zu Fuß machen.
strtok_r ist da schon etwas eleganter, und wohl auch schneller.
Ich werde wohl den Code aus der String-Lib etwas modifizieren. Und
einfach den Teil rauslassen, der die mehrfachen Trennzeichen
überspringt. Dann hätte ich genau was ich suche.
Gruß Holger