7 Stimmen

C: Leere Token aus einer Zeichenkette mit strtok zerlegen

Meine Anwendung erzeugt Zeichenketten wie die folgende. Ich muss die Werte zwischen dem Trennzeichen in einzelne Werte zerlegen.

2342|2sd45|dswer|2342||5523|||3654|Pswt

Ich verwende strtok um dies in einer Schleife zu tun. Für das fünfte Token erhalte ich 5523. Ich muss jedoch den leeren Wert zwischen den beiden Trennzeichen berücksichtigen || auch. 5523 sollte der sechste Token sein, so wie ich es verlange.

token = (char *)strtok(strAccInfo, "|");

for (iLoop=1;iLoop<=106;iLoop++) { 
            token = (char *)strtok(NULL, "|");
}

Irgendwelche Vorschläge?

2 Stimmen

Strtok() ist wohl das Schlimmste, was der C-Standard zu bieten hat. Sie könnten Ihren eigenen Parser schreiben.

8voto

Patrick Schlüter Punkte 10870

In diesem Fall bevorzuge ich oft eine p2 = strchr(p1, '|') Schleife mit einer memcpy(s, p1, p2-p1) innen. Es ist schnell, zerstört den Eingabepuffer nicht (und kann daher mit const char * ) und ist wirklich portabel (sogar auf Embedded).

Außerdem ist sie reentrant; strtok ist es nicht. (Übrigens: Reentrant hat nichts mit Multithreading zu tun. strtok bricht bereits bei verschachtelten Schleifen. Man kann verwenden strtok_r aber es ist nicht so tragbar.)

0 Stimmen

Ich habe Ihren Beitrag genutzt und meinen Code aktualisiert. Danke! Ich habe den Code, den ich verwende unten als Antwort, wenn Sie interessiert sind.

0 Stimmen

Danke, inspiriert von Ihrer Antwort habe ich ce

0 Stimmen

Tut mir leid, Patrick, aber könntest du ein bisschen genauer erklären, wie deine Lösung funktioniert? Ich vermute s ist die ursprüngliche Zeichenkette, aber was sind p1 y p2 ?

3voto

user411313 Punkte 3800
char *mystrtok(char **m,char *s,char c)
{
  char *p=s?s:*m;
  if( !*p )
    return 0;
  *m=strchr(p,c);
  if( *m )
    *(*m)++=0;
  else
    *m=p+strlen(p);
  return p;
}
  • ablaufinvariant
  • thread-safe
  • streng ANSI-konform
  • benötigt einen unbenutzten Hilfe-Zeiger vom Aufruf Kontext

z.B..

char *p,*t,s[]="2342|2sd45|dswer|2342||5523|||3654|Pswt";
for(t=mystrtok(&p,s,'|');t;t=mystrtok(&p,0,'|'))
  puts(t);

z.B..

char *p,*t,s[]="2,3,4,2|2s,d4,5|dswer|23,42||5523|||3654|Pswt";
for(t=mystrtok(&p,s,'|');t;t=mystrtok(&p,0,'|'))
{
  char *p1,*t1;
  for(t1=mystrtok(&p1,t,',');t1;t1=mystrtok(&p1,0,','))
    puts(t1);
}

Ihre Arbeit :) char *c als Parameter 3 implementieren

2voto

Romain Hippeau Punkte 23654

Bei einem ersten Aufruf erwartet die Funktion einen C-String als Argument für str, dessen erste Zeichen wird als Startposition für die Suche nach Token verwendet wird. Bei nachfolgenden Aufrufen erwartet die Funktion einen Null-Zeiger und verwendet die Position direkt nach dem Ende des letzten Tokens als neue Startposition für die Scannen.

Den Anfang und das Ende zu bestimmen eines Tokens zu bestimmen, scannt die Funktion zunächst von der Startposition aus nach dem ersten Zeichen, das nicht in Begrenzungszeichen enthalten ist (dies wird der Anfang des Tokens). Und dann wird von diesem Anfang des Tokens ausgehend des Tokens nach dem ersten Zeichen das in Begrenzungszeichen enthalten ist, das zum das Ende des Tokens wird.

Das bedeutet, dass es alle "|"-Zeichen am Anfang eines Tokens überspringt. Damit ist 5523 das 5. Token, was Sie bereits wussten. Ich wollte nur erklären, warum (ich musste es selbst nachschlagen). Dies besagt auch, dass Sie keine leeren Token erhalten werden.

Da Ihre Daten auf diese Weise aufgebaut sind, gibt es mehrere mögliche Lösungen:
1) alle Vorkommen von || suchen und durch | | ersetzen (ein Leerzeichen einfügen)
2) Führe 5 mal strstr aus und finde den Anfang des fünften Elements.

0 Stimmen

Vielen Dank für die Informationen. Hoffentlich kann ich mich beim nächsten Mal daran erinnern :-D Ihre erste Lösung bringt meine Ergebnisse ein wenig durcheinander, weil es gültige Komponenten innerhalb der Zeichenkette gibt, die ein Leerzeichen zwischen den Pipes zurückgeben. Die zweite Lösung könnte mühsam werden und ist wahrscheinlich nicht implementierbar, da die Zeichenfolge für verschiedene Datensätze unterschiedlich sein kann.

0 Stimmen

@Bash - Tut mir leid, dass ich Ihnen nicht weiterhelfen konnte :(

0 Stimmen

Oh, Sie waren eine große Hilfe... Information ist Macht in unserem Bereich, nicht wahr?

2voto

Das ist eine Einschränkung der strtok . Die Designer hatten durch Leerzeichen getrennte Token im Sinn. strtok macht sowieso nicht viel; entwickeln Sie einfach Ihren eigenen Parser. Die C FAQ enthält ein Beispiel .

1 Stimmen

Der von Ihnen gepostete Link hat mir einige nützliche Informationen geliefert. Danke!

1voto

Chris Punkte 101

Versuchen Sie stattdessen, strsep zu verwenden: Strsep-Referenz

0 Stimmen

Na ja :-) Ich programmiere hauptsächlich unter UNIX, und das wird mir jetzt sicher nützlich sein :-)) Ich habe noch nie davon gehört.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X