Forum: Mikrocontroller und Digitale Elektronik String durch zwei eingrenzende Strings extrahieren


von Myjestic E. (myjestic)


Lesenswert?

Hallo,

ich habe einen großen String und zwei kleinere "Delimiterstrings". Nun 
möchte ich alles aus dem großen String extrahieren was zwischen den 
beiden "Delimiterstrings" steht.
1
char input_line[100] = "Value1 alles was dazwischen steht Value2 irgendwas Value1";
2
char Filtered_Value[100];
3
4
char * ptr_string1 = strstr(input_line,"Value1");
5
char * ptr_string2 = strstr(input_line,"Value2");
6
strncpy(Filtered_Value, input_line, ptr_string2-ptr_string1);

Rauskommen soll dann:
Filtered_Value = " alles was dazwischen steht "

Problematisch ist auch, dass er den zweiten Dilimiter erst von dort aus 
suchen soll, wo er den ersten Dilimiter gefunden hat.

strncpy ist glaube nicht ganz die richtige Funktion dafür, weil hier 
immer vom ersten Char begonnen wird. Wie kann ich das lösen?

von Walter Tarpan (Gast)


Lesenswert?

Kennt Deine Programmierumgebung reguläre Ausdrücke?

von Myjestic E. (myjestic)


Lesenswert?

Sry vergessen zu erwähnen, dass ich in der Arduino IDE unterwegs bin.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Kai I. schrieb:
> Hallo,
> Problematisch ist auch, dass er den zweiten Dilimiter erst von dort aus
> suchen soll, wo er den ersten Dilimiter gefunden hat.

Du kannst sowohl der strncpy- als auch der strstr-Funktion einen Offset 
mitgeben, also ab welcher Position kopiert/gesucht werden soll.

Allgemein:

strncpy (pointer + position, ....
strstr (pointer + position, ....

Also: Beim Suchen des 2. Delimiters gibst Du als Pointer einfach

     ptr_string1 + strlen ("Value1")
an.

Beim Kopieren gibst Du ebenso an:

     ptr_string1 + strlen ("Value1")

Achte darauf, die Anzahl der Zeichen korrekt zu berechnen. Dann ist 
alles ganz einfach.

von Karl H. (kbuchegg)


Lesenswert?

>> Hallo,
>> Problematisch ist auch, dass er den zweiten Dilimiter erst von dort aus
>> suchen soll, wo er den ersten Dilimiter gefunden hat.
>
> Du kannst sowohl der strncpy- als auch der strstr-Funktion einen Offset
> mitgeben, also ab welcher Position kopiert/gesucht werden soll.

Allgemeiner gesagt:

strcpy oder strcat oder strstr fangen genau an der Position mit ihrer 
Arbeit an, die man ihnen als den Start vorgibt.

Das kann ganz am Anfang eines Strings sein
1
char input_line[100] = "Value ....
2
3
char * ptr_string1 = strstr(input_line,"Value1");

das kann aber auch ein ganz anderer Anfang sein
1
...
2
char * ptr_string1 = strstr(input_line + 5,"Value1");
3
4
// oder
5
6
char * ptr_string1 = strstr(&input_line[5],"Value1");

das kann aber auch eine Startadresse sein, die man irgendwo anders her 
hat. Zb aus einem früheren Aufruf von strstr
1
char * ptr_string1 = strstr(input_line,"Value1");
2
if( ptr_string1 != NULL ) {    // gefunden?
3
  char * ptr_string2 = strstr(ptr_string1,"Value2");  // beginne dort, wo Value1 gefunden wurde
4
5
  ....

strstr, oder allgemein allen str... Funktionen ist das ziemlich egal, ob 
die Adresse, die sie bekommen den Anfang des Strings markiert oder ob 
diese Adresse irgendwo mitten in den String hineinzeigt. Ab der Adresse, 
die übergeben wird, ab dort wird gearbeitet.

Daher ist es in C auch so wichtig, mit Pointern bzw. Pointer-Arithmetik 
nicht auf Kriegsfuss zu stehen. Was viele als unnötige Hürde ansehen ist 
in Wirklichkeit ein einfaches aber enorm mächtiges Werkzeug.

von Myjestic E. (myjestic)


Lesenswert?

Einwandfrei. Vielen Dank für die Erläuterung. Das Ganze muss dann so 
aussehen damit es funktioniert:
1
char input_line[100] = "Value1 alles was dazwischen steht Value2 irgendwas Value1";
2
char Filtered_Value[100];
3
4
char DelimString1[] = "Value1";
5
char DelimString2[] = "Value2";
6
        
7
char * ptr_string1 = strstr(input_line,DelimString1);
8
char * ptr_string2 = strstr(ptr_string1+strlen(DelimString1),DelimString2);
9
strncpy(Filtered_Value, ptr_string1+strlen(DelimString1), (ptr_string2-(ptr_string1+strlen(DelimString1))));
10
11
puts(Filtered_Value);

von Myjestic E. (myjestic)


Lesenswert?

Danke auch Dir Karl Heinz. Ich zähle mich leider auch zu den 
Kriegsfüßern. Aber ganz drumherum kommt man halt nicht und so schlimm 
wie man immer denkt ist es am Ende ja auch nicht :)-

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Kai I. schrieb:
>
1
> char * ptr_string1 = strstr(input_line,DelimString1);
2
> char * ptr_string2 = 
3
> strstr(ptr_string1+strlen(DelimString1),DelimString2);
4
>

Beachte auch Karl Heinz' Hinweis, den Rückgabewert von strstr() zu 
prüfen. Wenn der erste strstr()-Aufruf den Delimiter-String nicht 
findet, ist ptr_string1 == NULL. Das macht sich dann gar nicht so gut 
beim 2. Aufruf.

von Karl H. (kbuchegg)


Lesenswert?

Kai I. schrieb:
> Einwandfrei. Vielen Dank für die Erläuterung. Das Ganze muss dann so
> aussehen damit es funktioniert:

wobei man da noch vereinfachen könnte, um dem Ganzen auch noch den 
Nimbus des Unlesbaren zu nehmen.
wenn du den ptr_string1 erst mal hast, dann brauchst du den Wert 
eigentlich nicht mehr wirklich. Was du brauchst, das ist der Pointer an 
den Anfang der Einfügestelle. Ausgehend vom erhaltenen ptr_string1 
weisst du aber wo der liegt.

Ausserdem solltest du doch noch gegen den Fall absichern, dass die 
Delimiter nicht gefunden werden.
1
char input_line[100] = "Value1 alles was dazwischen steht Value2 irgendwas Value1";
2
char Filtered_Value[100];
3
4
  char DelimString1[] = "Value1";
5
  char DelimString2[] = "Value2";
6
 
7
  char* leftDelimiter = strstr(input_line,DelimString1);
8
  if( leftDelimiter ) {
9
    leftDelimiter += strlen( DelimString1 );  // an den Anfang der eigentlichen Einfügestelle
10
11
    char * rightDelimiter = strstr(leftDelimiter, DelimString2);
12
    if( rightDelimiter ) {
13
      strncpy( Filtered_Value, leftDelimiter, rightDelimiter - leftDelimiter );
14
      puts( Filtered_Value );
15
    }

Als Faustregel kannst du nehmen: wenn der Code nur so von strlen 
strotzt, dann lässt sich das meistens deutlich vereinfachen. Unter 
Umständen auch mit ein paar Hilfsvariablen.

von Dirk B. (dirkb2)


Lesenswert?

Zu strncpy ist noch zu sagen, dass es die '\0' nicht mit kopiert, 
wenn das n (die Länge) erreicht ist.
Die musst du dann selber nachtragen (strlen geht da aber nicht).

strncat hängt die '\0' jedoch immer an.

Wenn der Zielbereich leer ist, dann erfüllt das schon deinen Zweck.
Ein
1
Filtered_Value[0] = 0;
 vor dem strncat reicht da aus.

von MaWin (Gast)


Lesenswert?

Kai I. schrieb:
> char * ptr_string1 = strstr(input_line,"Value1");
> char * ptr_string2 = strstr(input_line,"Value2");
>
> Rauskommen soll dann:
> Filtered_Value = " alles was dazwischen steht "
>
> Problematisch ist auch, dass er den zweiten Dilimiter erst von dort aus
> suchen soll, wo er den ersten Dilimiter gefunden hat.

Na dann mach das doch:

char * ptr_string1 = strstr(input_line,"Value1");
char * ptr_string2 = strstr(ptr_string1+strlen("Value1"),"Value2");

> strncpy(Filtered_Value, input_line, ptr_string2-ptr_string1);

Wieso von input_line und nicht ptr_string1+strlen("Value1") ?

Schlag noch mal nach, was strncpy macht, wenn der String input_line 
länger ist als ptr_string2-ptr_string1. Du möchtest nämlich einen '\0' 
Terminator hinter dem Ergebnisstring, und den nicht nur, weil char 
Filtered_Value[100] vielleicht zufälligerweise mit '\0'en gefüllt ist.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.