C-String teilen
Steffanie
- programmiertechnik
Hallo,
eigentlich sollte ich ja bei solch einem schönen Wetter nicht vor dem PC rumsitzen, aber ich muss das noch hinbekommen.
Ich habe einen String (also char-Array), den ich erstmal teilen muss, da dort einiger Schrott drin ist. Danach will ich den String mittels eines Trennzeichen in mehrer Strings (char-Arrays) teilen. Leider klappt das mit den mehrdimensionalen arrays einfach nicht. Hoffentlich kann mir jemand helfen...
Tausend Dank!
Gruß Steffi
hier mein Ansatz:
#include <stdio.h>
#include <string.h>
int main(void)
{
char empfangspuffer[] = "aklsdfjlkasdjflkasjdflkasdj#<start>#6#920FC1CD#Herr#Mustermann";
char trennzeichen[] = "#";
char startflag[] = "<start>";
char empfangsdaten[40];
char *strpointer;
char *wort_aktuell;
char empfangsdaten_einzeln[5][10];
int i = 0;
strpointer = strstr(empfangspuffer, startflag);
strcpy(empfangsdaten,strpointer);
wort_aktuell = strtok(empfangsdaten, trennzeichen);
strcpy(empfangsdaten_einzeln[i],wort_aktuell);
while( wort_aktuell != NULL )
{
wort_aktuell = strtok(NULL, trennzeichen);
i++;
strcpy(empfangsdaten_einzeln[i],wort_aktuell);
}
return 0;
}
hi!
Da hast du wohl die Reihenfolge etwas durcheinandergebracht in deiner while-
Schleife:
while( wort_aktuell != NULL ) {
wort_aktuell = strtok(NULL, trennzeichen);
i++;
strcpy(empfangsdaten_einzeln[i],wort_aktuell);
}
Hier musst du zwischen strtok und strcpy ueberpruefen, ob es ein Ergebnis gab.
Aber du hast nur eine Ueberpruefung am Anfang der Schleife eingebaut. Richtig
waere zum Beispiel:
while( wort_aktuell != NULL ) {
strcpy(empfangsdaten_einzeln[i],wort_aktuell);
wort_aktuell = strtok(NULL, trennzeichen);
i++;
}
bye, Frank!
Hi!
Da hast du wohl die Reihenfolge etwas durcheinandergebracht in deiner while-
Schleife:
OHHHHH MAAAAANNN! Ich sollte echt raus an die Sonne!
Vielen Dank!
Gruß Steffi!
Hallo Steffi,
Da hast du wohl die Reihenfolge etwas durcheinandergebracht in deiner while-Schleife:
OHHHHH MAAAAANNN! Ich sollte echt raus an die Sonne!
oder vielleicht besser raus aus der Sonne? ;-)
Sorry, ich bin normalerweise nicht fies, aber bei der Steilvorlage ...
*scnr*
Martin
oder vielleicht besser raus aus der Sonne? ;-)
Sorry, ich bin normalerweise nicht fies, aber bei der Steilvorlage ...
:-) Könnte man auch meinen. Aber jetzt kann ich wirklich ohne schlechtes Gewissen raus... nen Sonnenstich kann ich mir jetzt auch nicht mehr holen...
Danke nochmal!
Gruß Steffi
bye, Frank!
Hey, dich gibt's ja auch noch ;)
Viele Grüße!
_Dirk
Moin.
Ich hoffe mal, du kannst garantieren, dass die Länge deiner Daten die hardcodierten Feldbreiten nie überschreiten...
Verwende besser eine Funktion, die Strings beliebiger Länge 'splitten' kann. Ich habe sowas tatsächlich bei mir rumfliegen, für Bug-Freiheit übernehme ich allerdings keine Garantie ;)
#include <stdlib.h>
#include <string.h>
char ** strsplit(const char * input, char sep, size_t max_tokens)
{
char ** tokens = NULL;
char * str = NULL;
tokens = malloc(sizeof(char *) * (max_tokens + 1));
if(!tokens) goto failed;
size_t size = strlen(input) + 1;
str = malloc(size);
if(!str) goto failed;
memcpy(str, input, size);
tokens[0] = str;
char ** current = &tokens[1];
for(; *str; ++str)
{
if(*str != sep) continue;
if(!--max_tokens) break;
*str = '\0';
*current++ = str + 1;
}
*current++ = NULL;
tokens = realloc(tokens, (char *)current - (char *)tokens);
if(!tokens) goto failed;
return tokens;
failed:
if(tokens) free(tokens);
if(str) free(str);
return NULL;
}
Die Funktion gibt ein Array von char* auf die einzelnen Teilstrings zurück, im Fehlerfall NULL. Der letzte Array-Eintrag ist stets NULL.
Christoph
PS: Nach Verwendung Speicher freigeben nicht vergessen...
char ** tokens = strsplit(input, sep, 32);
free(*tokens); // erster Array-Eintrag zeigt auf allozierten String
free(tokens); // Speicher des Arrays freigeben
CHristoph
Hallo,
eigentlich sollte ich ja bei solch einem schönen Wetter nicht vor dem PC rumsitzen, aber ich muss das noch hinbekommen.
Ich habe einen String (also char-Array), den ich erstmal teilen muss, da dort einiger Schrott drin ist. Danach will ich den String mittels eines Trennzeichen in mehrer Strings (char-Arrays) teilen. Leider klappt das mit den mehrdimensionalen arrays einfach nicht. Hoffentlich kann mir jemand helfen...
Falls es wirklich nur ein einzelnes Trennzeichen ist,
kannst Du es Dir und der CPU auch leicht machen:
Viele Grüße
Andreas
Bsp:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(void) {
char empfangspuffer[] = "aklsdfjlkasdjflkasjdflkasdj#<start>#6#920FC1CD#Herr#Mustermann";
char trennzeichen = '#';
char *kopie = strdup(empfangspuffer); // Damit Original unveraendert bleibt.
char **result; // Hier kommen die Pointer auf die Teilstrings hinein
int n=0; // ... und hier die Anzahl
char *tmp;
int i;
for(tmp=kopie; *tmp; ++tmp)
if(*tmp==trennzeichen) { *tmp=(char)0; ++n; }
++n; // Es gibt einen Teilstring mehr als '#'s
result = (char**)malloc(n*sizeof(char*));
tmp = kopie;
for(i=0; i<n; ++i) {
result[i] = tmp;
tmp += strlen(tmp)+1;
}
// Ergebnisausgabe
printf("Anzahl der Teilstrings: %i\n", n);
for(i=0; i<n; ++i)
printf("Teilstring %i: %s\n", i+1, result[i]);
// ggf. aufraeumen
free(result);
free(kopie);
return 0;
}
Moin.
Falls es wirklich nur ein einzelnes Trennzeichen ist,
kannst Du es Dir und der CPU auch leicht machen:
- Den gesamten String kopieren (nur, falls Du den
Empfangspuffer noch anderweitig brauchst, ansonsten
kann die Manipulation direkt im Empfangspuffer geschehen...)- Alle '#' in der Kopie durch (char)0 ersetzen.
Ich möchte dich jetzt nicht enttäuschen, aber das ist genau das, was Steffanies Lösung bereits tut (strtok ersetzt die Trennzeichen im String, daher legt Steffanie korrekterweise vorher eine Kopie von empfangspuffer in empfangsdaten ab).
- Ein Pointer-Array vom typ char** anlegen, welches
auf die jeweiligen Teilstring-Fragmente zeigt.
Das macht Steffanie allerdings nicht, sondern sie kopiert (vermutlich unnötigerweise - aber wer kann wissen, wie das ganze weiter verarbeitet werden soll?) den String erneut in ein weiteres Array.
Meine Lösung arbeitet im übrigen genauso wie deine, nur, dass ich auf Rückgabewerte der malloc's (bei dir strdup) prüfe und im Gegensatz zu dir den String nur einmalig durchlaufe: Du tust dies einmal zum Ersetzen der Trennzeichen, und ein weiteres mal, um die Pointer in result abzulegen. Das ist nicht wirklich effizient...
Christoph
Hallo Christoph,
Meine Lösung arbeitet im übrigen genauso wie deine, nur, dass ich auf Rückgabewerte der malloc's (bei dir strdup) prüfe und im Gegensatz zu dir den String nur einmalig durchlaufe: Du tust dies einmal zum Ersetzen der Trennzeichen, und ein weiteres mal, um die Pointer in result abzulegen. »»
Christoph
das liegt daran, dass man bei Deiner
Funktion einen Parameter max_tokens
angeben muss und überzählige Tokens dann
einfach ignoriert werden, während meine Routine
theoretisch beliebig lange Eingangsstrings
zerlegt (mal von Speicherbegrenzungen
und den fehlenden Sicherheitsabfragen abgesehen...).
Der doppelte Durchlauf ergibt sich daraus, dass im
ersten Durchlauf die Trennzeichen gezählt werden, damit
result allozieren zu können.
Viele Grüße und noch ein schönes
verlängertes Wochenende
Andreas