String für Auswertung Trennen

Gast #752287
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
Gast #753347
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
Gast #753375
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ß
Gast #753397
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?
Gast #753423
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ß
#753442
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren