Forum: Mikrocontroller und Digitale Elektronik Commando aus String suchen..


von Jan H. (janiiix3)


Lesenswert?

Halli Hallo,

stehe gerade irgendwie auf dem Schlauch.
Ich möchte gerne ein Kommando aus einem String raus suchen.
Übergeben tue ich der Funktionen einen String und möchte mit einem 
Zeiger Array voller Kommandos vergleichen. Ist ein Kommando mit einem 
aus dem Zeiger Array identisch, soll das übernommen werden. Wenn nicht 
soll weitergesucht werden bis alle Elemente untersucht wurden..

Bekomme es gerade nicht hin :(
1
unsigned int parseString(char str[], parse_t *ParseInfo,  char delimiter)
2
{
3
  #define DELIMITER_BYTE    0
4
  #define FIRST_COMMAND    1
5
  #define SECOND_COMMAND    2
6
  #define BEGINN_RAW_BYTE    3
7
  
8
  #define POSSIBLE_COMMANDO  ( 1<<0 )
9
  unsigned int tempCnt        = 0x00;
10
  unsigned int ptrCnt          = 0x00;
11
12
  
13
  while(*str != delimiter)// pointer to delimiter
14
  {
15
    str++;
16
    if (*str == '\0')
17
    return 1;
18
  }; 
19
  
20
  ParseInfo->receivedCmd[DELIMITER_BYTE] = *str;  
21
  
22
  while(*str)
23
  {
24
    if(*str == *ParseInfo->allowCmd[0])
25
    {
26
      printf("Erfolgreich!");
27
      break;  
28
    }
29
  }
30
31
  return 0;
32
}

delimiter soll der Anfang eines Kommandos darstellen.

von Florian (Gast)


Lesenswert?

Hallo Jan,

was genau funktioniert denn nicht? Hat es einen Grund, warum Du keine 
Funktionen aus der string.h verwendest? Damit kannst Du Zeichen, Strings 
und Teilstrings suchen.

Gruß
Florian

von sek (Gast)


Lesenswert?

Lass mich raten...parseString kehrt nie zurück, weil die zweiten 
while(...) Schleife nicht abbricht...

von Peter D. (peda)


Lesenswert?

Florian schrieb:
> Hat es einen Grund, warum Du keine
> Funktionen aus der string.h verwendest?

Wie z.B. strtok, strcmp

von Jan H. (janiiix3)


Lesenswert?

Peter D. schrieb:
> Florian schrieb:
>> Hat es einen Grund, warum Du keine
>> Funktionen aus der string.h verwendest?
>
> Wie z.B. strtok, strcmp

Suchen diese Funktionen auch mitten im String?

von Florian (Gast)


Lesenswert?

Jan H. schrieb:
> Suchen diese Funktionen auch mitten im String?

Ja.

schau mal hier:

http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/011_c_arrays_013.htm

von Dirk B. (dirkb2)


Lesenswert?

Lass dir doch mal die Zwischenergebnisse von str ausgeben (mit printf 
oder dem Debugger)

Bei printf kannst du die noch zwischen Trennzeichen setzen, damit du 
Leerzeichen besser erkennen kannst.
1
printf("<%s>\n", str);


Nach der ersten while-Schleife zeigt str auf einen delimiter.
Aber damit fangen deine Kommandos sicher nicht an.

von Mmhm (Gast)


Lesenswert?

Ich nehme gerne folgendes:
1
#include <string.h>
2
3
char *RX UART_RX_Buffer[0];
4
5
if(strstr(RX, "set") != NULL){
6
    //da seht set im RX: Kommando set ausführen
7
}
Must halt stat "set" einen pointer auf ein Element in deinem Array 
setzen.
strstr liefert einen pointer auf den string zurück, was praktisch ist, 
um damit weiterzuarbeiten.

Vorteil:
Portabel, weil Standarad-C-Funktion, simpel.

Nachteil:
Kein Sparwunder.

von Nop (Gast)


Lesenswert?

Mmhm schrieb:
> Ich nehme gerne folgendes:

> char *RX UART_RX_Buffer[0];
>
> if(strstr(RX, "set") != NULL){
>     //da seht set im RX: Kommando set ausführen
> }

Normalerweise sind solche RX-Buffer ja als Ringbuffer ausgeführt. Wenn 
ein Teil des Kommandos vor dem Wraparound steht und der Rest dann am 
Anfang des Ringbuffers weitergeht, wird es nicht gefunden. Sieht mir 
also nicht nach einer zuverlässigen Lösung aus.

von asdfasd (Gast)


Lesenswert?

1
#include <stdio.h>
2
#include <string.h>
3
4
char *find_cmd(char *str, char del, char *cmds)
5
{
6
    while (*str)
7
        if (*str++ == del)
8
            if (strchr(cmds, *str))
9
                return str;
10
    return 0;
11
}
12
13
int main(int argc, char **argv)
14
{
15
    char *str = ":a:b..:bb..:..:a..:";
16
17
    while (str = find_cmd(str, ':', "ab"))
18
        switch (*str) {
19
            case 'a': printf("Found a\n"); break;
20
            case 'b': printf("Found b\n"); break;
21
        }
22
23
    return 0;
24
}

von asdfasd (Gast)


Lesenswert?

Ehm ... die Suche nach dem Begrenzer kann man natürlich auch mit strchr 
machen:
1
char *find_cmd(char *str, char del, char *cmds)
2
{
3
    while (str = strchr(str, del))
4
        if (strchr(cmds, *++str))
5
            return str;
6
    return 0;
7
}

von Mmhm (Gast)


Lesenswert?

Nop schrieb:
> Mmhm schrieb:
>> Ich nehme gerne folgendes:
>
>> char *RX UART_RX_Buffer[0];
>>
>> if(strstr(RX, "set") != NULL){
>>     //da seht set im RX: Kommando set ausführen
>> }
>
> Normalerweise sind solche RX-Buffer ja als Ringbuffer ausgeführt. Wenn
> ein Teil des Kommandos vor dem Wraparound steht und der Rest dann am
> Anfang des Ringbuffers weitergeht, wird es nicht gefunden. Sieht mir
> also nicht nach einer zuverlässigen Lösung aus.

Das kommt drauf an, wie man die UART umgesetzt hat, und in welcher 
Umgebung.

Meine Lösung ist halt eben asynchron. Der Emfpang passiert in einer ISR, 
die befüllt den Buffer, wenn das "Stopp-Zeichen" kommt oder der Buffer 
überlaufen würde, wird ein Flag gesetzt. Überschüssige Zeichen werden 
ignoriert, statt vorhanden Daten zu überschreiben.
Die Ausführung des Kommandos passiert komplett asynchron, wenn dem 
Controller grad fad ist. Und das kann auch hunderte ms später sein. 
Danach wird der Buffer gelöscht.
Ich behaupte auch nicht dass das allgemein sinnvoller ist als andere 
Implementierungen oder ein Ringpuffer.
Aber das hier funktioniert auch dann zuverlässig, wenn der Controller 
bei 99,99% Auslastung ist.
Nachteil ist halt die begrenzte Länge einer Message.

Aber sei es wie es sei:
Das Thema war weder um UARTs, noch um Ringpuffer, sondern das finden 
eines Kommandos in einem String. Und das geht fallweise eben auch mit 
strstr.

von Jan H. (janiiix3)


Lesenswert?

asdfasd schrieb:
>
1
> #include <stdio.h>
2
> #include <string.h>
3
> 
4
> char *find_cmd(char *str, char del, char *cmds)
5
> {
6
>     while (*str)
7
>         if (*str++ == del)
8
>             if (strchr(cmds, *str))
9
>                 return str;
10
>     return 0;
11
> }
12
13
>

Okay. Das klappt soweit sehr gut. Wie untersuche ich jetzt den 
"Kommando" String nach dem Ende? Habe mir gedacht das ich als 
Kommandoende das '*' Zeichen nehme?!

von Joachim B. (jar)


Lesenswert?

mal als Beispiel ein Codeschnipsel
1
      if (Serial.available() > 0) 
2
      { char incomingByte = (char)Serial.read();
3
        if(incomingByte != 13 && incomingByte != 10 )  // Falls nicht Enter kommt muss der Text gespeichert werden in dem inText Array
4
        { if(isprint(incomingByte))
5
          { if(chr_cnt<(MAXBUFFER-2))
6
              serial_in_buff[chr_cnt++] = incomingByte;
7
            else
8
            { Serial.println(F("serBUF ov-> DEL"));
9
              memset(&serial_in_buff[0], 0, sizeof(serial_in_buff)); // 30.554 Bytes
10
              memset(&serial_in_command[0], 0, sizeof(serial_in_command)); // 30.554 Bytes
11
//              *serial_in_command=0;
12
              chr_cnt=0;
13
            } // if(chr_cnt<(MAXBUFFER-1))
14
          } // if(isprint(incomingByte))
15
        } // if(incomingByte != 13)
16
        else // Wenn das Enter ankommt
17
        { serial_in_buff[chr_cnt] = 0;
18
          chr_cnt = 0;
19
          strcpy(serial_in_command, serial_in_buff);
20
          memset(&serial_in_buff[0], 0, sizeof(serial_in_buff)); // 30.554 Bytes
21
22
          if(strlen(serial_in_command))
23
          { Serial.println(F("")); Serial.print(serial_in_command);  Serial.println(F(" -> erkannt")); 
24
                  
25
            if( !strcmp(serial_in_command, "help") || ( !strcmp(serial_in_command, "?") && strlen(serial_in_command)==1 ) )
26
            { // help screen
27
              Serial.println(F("\ncommands: \n"));
28
          
29
              Serial.println(F("hell, hellp, hellm, hellxx(0-10)"));
30
              Serial.println(F("con, conp, conm, conxx(55-75)"));
31
              Serial.println(F("date, dateJJJJ/MO/TA"));
32
              Serial.println(F("time, timeHH:MM:SS"));
33
        
34
              Serial.println(F("up, up?, up07:30"));
35
              Serial.println(F("down"));
36
          
37
              Serial.println(F("stat"));
38
              Serial.println(F("fstat"));
39
              Serial.println(F("i2ceep"));
40
        
41
              Serial.println(F("reset"));
42
              Serial.println(F(""));
43
              memset(&serial_in_command[0], 0, sizeof(serial_in_command));
44
            }
45
        
46
            else if( strstr(serial_in_command, "hell") )
47
            { if( !strcmp(serial_in_command, "hellp") )
48
                backlight_p();
49
              else if( !strcmp(serial_in_command, "hellm") )
50
                backlight_m();
51
              else if( !strncmp(serial_in_command, "hell", 4) && strlen(serial_in_command)>4 && strlen(serial_in_command)<7 )
52
              { // "hell??"
53
                uint8_t tmp_hell = atoi( (char *)serial_in_command + 4);
54
                memset(&serial_in_command[0], 0, sizeof(serial_in_command));
55
                if( tmp_hell>=MIN_BL && tmp_hell<=MAX_BL )
56
                {  MY_EEP_VAR.backlicht = tmp_hell;
57
                   analogWrite(NOK_BL, pgm_read_byte(&pwmtable_11C[MY_EEP_VAR.backlicht])); 
58
                   con_hell_stat(true);  
59
                }
60
                else
61
                { sprintf_P(s_out_str, PSTR("hellxx (%d)-(%d)"), MIN_BL, MAX_BL); Serial.println(s_out_str); // 30.608 Bytes
62
                }
63
              } // if( !strcmp(serial_in_command, "hell??") )
64
              memset(&serial_in_command[0], 0, sizeof(serial_in_command));
65
            } // if( !strcmp(serial_in_command, "hell") )

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.