Forum: Mikrocontroller und Digitale Elektronik String für Auswertung Trennen


von µC-noob (Gast)


Lesenswert?

Hallo,

ich steh mal wieder vor einem Problem, bei dem bisher jeder meiner 
Lösungsversuche gescheitert ist,....

Über den UART empfange ich Daten, die ausgewertet werden müssen:

IMMER dieser Art

">:SET?2\r\n"
">:RESET?2\r\n"
">:TOGGLE?2?1000\r\n

In einer Routine lese ich diese Zeichen nun charweise in einen Buffer 
ein, bis das \r
oder \n erkannt wird, danach möchte ich den string auswerten.

beispielsweise das hier
">:TOGGLE?2?1000\r\n

Soll nachher zu
str1 = ">:TOGGLE"
str2 = 2
str3 = 1000
konvertiert werden

Ihr seht, es gibt ein Kommando eingeleitet mit eiem ">:"
Danach folgen Eingaben, eingeleitet mit einem "?", jedem Fragezeichen 
folgt eine neue Zahl, bis das \r\n kommt, was das Ende des kommandos 
anzeigt.

Gibt es da Bibliotheksfunktionen, oder wie Trenne ich den String am 
besten??

Danke und Gruß
Joe

von Karl H. (kbuchegg)


Lesenswert?

Schau dir strtok() an. Mit dieser Funktion ist das nicht
weiter problematisch.

von µC-noob (Gast)


Lesenswert?

Hi,
danke erstmal,

strtok, gibt es in meiner Bibliothek nicht,
aber dafür strtok_r

Folgendes Programm steht:
1
struct getCmd_t
2
{
3
  char  cmd[20];
4
  char  Par1[20];
5
  char  Par2[20];
6
  char  Par3[20];
7
};
8
9
void splitCommand(void) //(char *rxBuffer)
10
{
11
  struct getCmd_t actCommand;
12
13
  char *testString =  ">:trigger?2?1000\0"; //">:spcSet?2?R?25?7?R\0";
14
  char *token;
15
  char *tmp;
16
17
  token = strtok_r( testString, ">:?", &tmp );
18
  strcpy( actCommand.cmd, token );
19
20
  token = strtok_r( NULL, "?", &tmp ); 
21
  strcpy( actCommand.Par1, token );
22
23
  token = strtok_r( NULL, "?", &tmp );
24
  strcpy( actCommand.Par2, token );
25
26
  token = strtok_r( NULL, "?", &tmp );
27
  strcpy( actCommand.Par3, token );
28
29
  add_menutext(&LCDLine1[0], actCommand.cmd, 0);
30
  add_menutext(&LCDLine2[0], actCommand.Par1, 0);
31
  add_menutext(&LCDLine3[0], actCommand.Par2, 0);
32
  add_menutext(&LCDLine4[0], actCommand.Par3, 0); 
33
}

Mein Problem,
ich möchte dieses Dynamisch gestalten, so dass nicht auf fest vier 
Parameter geteilt wird, sondern bis zum Stringende.
bei strtok könnte man ja mit
while(token != NULL) arbeiten,
aber mit strtok_r geht das ja nicht???,....

Wie immer, fehlt mir die zündende Idee zur Vorgehensweise,....

Jemand einen Vorschlag,
Vielen Dank...
Gruß Joe

von STK500-Besitzer (Gast)


Lesenswert?

Eine verkettete Liste mit den Parametern "bauen".

von µC-noob (Gast)


Lesenswert?

Ähm,...????
Hä??

Danke erstmal, aber....
Ok, dann doch etwas genauer bitte,...

Gruß

von µC-noob (Gast)


Lesenswert?

Ok, ok,

ich nehms zurück, mit ner whiile Tuts,....

Eine Frage noch:

Hier mein code:
1
void splitCommand(void) //(char *rxBuffer)
2
{
3
  struct getCmd_t actCommand;
4
5
  char i = 0;
6
  char *testString =  ">:trigger?2?1000\0"; //">:spcSet?2?R?25?7?R\0";
7
  char *token;
8
  char *tmp;
9
10
  token = strtok_r( testString, ">:?", &tmp );
11
  strcpy( actCommand.cmd, token );
12
  while ( token != 0)
13
  {   i = i + 1;
14
    token = strtok_r( NULL, "?", &tmp ); 
15
    if ( i == 1 )
16
      strcpy( actCommand.Par1, token );  
17
    else if( i == 2)
18
      strcpy( actCommand.Par2, token );
19
    else if( i == 3)
20
      strcpy( actCommand.Par3, token );
21
  }
22
23
  add_menutext(&LCDLine1[0], actCommand.cmd, 0);
24
  add_menutext(&LCDLine2[0], actCommand.Par1, 0);
25
  add_menutext(&LCDLine3[0], actCommand.Par2, 0);
26
  add_menutext(&LCDLine4[0], actCommand.Par3, 0); 
27
}

aber wie kann ich jetzt dieses Hier

actCommand.Par1

dynamisch speichern
am besten so:
1
      char Par[5][20]; //vermutlich syntaktisch falsch???
2
3
      strcpy( actCommand.Par[i], token );

Nur das ist ein chararray, und dan bräucht ich nen zweifaches array,
außerdem weiß ich nicht so ganz, wie ich auf sowas zugreifen soll??

Rat?

Danke, Danke,....

Gruß

von yalu (Gast)


Lesenswert?

> am besten so:
>
>       char Par[5][20]; //vermutlich syntaktisch falsch???
>
>       strcpy( actCommand.Par[i], token );

Ja, am besten so. Und vermutlich syntaktisch richtig ;-)

In Par kannst du nun bis zu 5 Tokens speichern, von denen jedes bis zu
19 Zeichen (plus die Stringendenull) lang sein darf.

Wo ist das Problem?

von Karl H. (kbuchegg)


Lesenswert?

> aber mit strtok_r geht das ja nicht???,....

Warum soll das mit strtok_r nicht gehen.
Beim kurzen Drüberschauen über die Doku von strtok_r
haben beide den gleichen Returnwert.

Edit: Hat sich ja mitlerweile erledigt.

von µC-noob (Gast)


Lesenswert?

Sehr schön,....

hier die Endlösung:
1
struct getCmd_t
2
{
3
  char  cmd[20];
4
  char  Par[PARA_AMOUNT][PARA_SIZE];
5
};
6
7
struct getCmd_t newCommand;
8
9
unsigned char splitCommand(void) //(char *rxBuffer)
10
{
11
  unsigned char i = 0;
12
  char *testString =  ">:spcSet?2?R?25?7?R\0";
13
  char *token;
14
  char *tmp;
15
16
  token = strtok_r( testString, "?", &tmp );
17
  strcpy( newCommand.cmd, token );
18
19
  while ( token != 0)
20
  {   
21
    token = strtok_r( NULL, "?", &tmp ); 
22
    strcpy( newCommand.Par[i], token );  
23
    i = i + 1;
24
    if( i >= ( PARA_AMOUNT - 1) )
25
      return 0; //not the most sensible solution but most effective!
26
  }
27
  return 1;
28
}

Gruß

von Karl H. (kbuchegg)


Lesenswert?

µC-noob wrote

>     if( i >= ( PARA_AMOUNT - 1) )
>       return 0; //not the most sensible solution but most effective!

Ein simples

      if( i == PARA_AMOUNT )
        return 0;

würde es auch tun :-)

Mit fällt auf, daß du in deiner Datenstruktur nirgends
vermerkt hast, wieviele Parameter denn nun extrahiert
werden konnten.

Das zweite: Du hast keine Sicherung eingebaut für den
Fall, dass die Parametergröße größer als PARA_SIZE wird.

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.