mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik strtok_r: Ergebnis unerwartet


Autor: Holger M. (nezaya)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.
char string[50] = "wert1,wert2,wert3,wert4,..."
char *tmp;
char *feld1;
char *feld2;
char *feld3;
...
feld1=strtok_r(string,",",&tmp);
feld2=strtok_r(NULL,",",&tmp);
feld3=strtok_r(NULL,",",&tmp);
...
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

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 ?

Autor: Werner Hoch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Holger M. (nezaya)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.