zahl aus uart string ermitteln

Gast #6221320
Lesenswert?

Hallo,

ich möchte gerne über uart variablen vorgeben. Dazu werden als ascii 
befehle und der wert gesendet.
z.B.

aktor1 100

aktor1 kann ich mittels strncmp ermitteln
strncmp(input, "aktor1", 6)

aber wie komme ich an die 100?
wenn nur die zahl da wäre, könnte ich es mit atoi machen. Gibt es da 
auch was, wo man die stelle mit angeben kann?
#6221332
Lesenswert?

Felix schrieb:
> en. Da

Uff Basse schrieb:
> schreibe anständig
> gross und klein.

hat er doch, nach "." und mit "Dazu"

Felix schrieb:
> aktor1

ist seine kleingeschriebene Variable!

Felix schrieb:
> uart variablen

Sind also Schreib oder Flüchtigkeitsfehler die kaum behindern, da gibt 
es Schlimmeres.
https://www.n-joy.de/leben/Deutsche-Sprache-12-Beweise-dass-Kleinigkeiten-Unterschied-machen,deutschesprache126.html
https://www.n-joy.de/leben/Warum-Kommas-so-wichtig-sind,deutschesprache150.html

Cyblord -. schrieb:
> Du kannst atoi doch auf jeden Startpunkt im String setzen. Einfach mit
> dem Plus Zeichen. Pointer sind doch Basiswissen in C. Nutze sie!

dito +1

Felix schrieb:
> strncmp(input, "aktor1", 6)

wie wäre es mit

strchr(input, ' ') +1 als Startwert für atoi?
#6221349
Lesenswert?

Uff Basse schrieb:
> Wenn man die Fehler noch dazu zählt die du übersehen hast dannn ...

meint der Unangemeldete mit 3n in dannn

Glashaus, du weisst schon :)

Felix schrieb:
> aktor1 100

also

Joachim B. schrieb:
> strchr(input, ' ') +1 als Startwert für atoi?

gäbe

print("was: %s, wieviel: %d \r\n", input, atoi(strchr(input, ' ') +1));

oder so, c mal vorausgesetzt. (kann trotzdem noch Fehler enthalten ohne 
den Dialekt zu kennen)
#6221493
Lesenswert?

Felix schrieb:
> aktor1 kann ich mittels strncmp ermitteln
> aber wie komme ich an die 100?

Üblicherweise kommen die Zeichen aus einem UART einzelzeichenweise und 
man möchte sie auch gleich verarbeiten damit man sie nicht unnötig 
speichern muss und ndafür Pufferspeicher (unbekannter Länge) reservieren 
muss.

Man malt sich am besten auf, welche Zeichen in welcher Reihenfolge 
kommen dürfen
1
--+--(a)--(k)--(t)--(o)--(r)--+--(1)--+--(=)--+--(0)--+--+-------+--+-------+--+--(\r)--(\n)--
2
  |                           |       |       |       |  |       |  |       |  |
3
  |                           +--(2)--+       +--(1)--+  +--(0)--+  +--(0)--+  |
4
  |                                           |       |  |       |  |       |  |
5
  |                                           +--(2)--+  +--(1)--+  +--(1)--+  |
6
  |                                           :       :  :       :  :       :  |
7
  |                                           +--(9)--+  +--(9)--+  +--(9)--+  |
8
  |                                                                            |
9
  +--(i)--(n)--(p)--(u)--(t)--+--(1)--+----------------------------------------+
10
  |                           |       |                                        |
11
  |                           +--(2)--+                                        |
12
  |                                                                            |
13
  +--(e)--(x)--(i)--(t)--------------------------------------------------------+
Jedem dieser Kringel gibt man eine Nummer
1
--+--(a)--(k)--(t)--(o)--(r)--+--(1)--+--(=)--+--(0)--+--+-------+--+-------+--+--(\r)--(\n)--
2
0 |   1    2    3    4    5   |   6   |   8   |   9   |  |       |  |       |  |   39    40
3
  |                           +--(2)--+       +--(1)--+  +--(0)--+  +--(0)--+  |
4
  |                               7           |  10   |  |  19   |  |  29   |  |
5
  |                                           +--(2)--+  +--(1)--+  +--(1)--+  |
6
  |                                           :  11   :  :  20   :  :  30   :  |
7
  |                                           +--(9)--+  +--(9)--+  +--(9)--+  |
8
  |                                              18         28         38      |
9
  +--(i)--(n)--(p)--(u)--(t)--+--(1)--+----------------------------------------+
10
  |  41   42   43   44   45   |  46   |                                        |
11
  |                           +--(2)--+                                        |
12
  |                              47                                            |
13
  +--(e)--(x)--(i)--(t)--------------------------------------------------------+
14
     48   49   50   51
das sind Zustände die man mit einer Zustandsmaschine abarbeitet
1
ch=getchar(); // vom UART
2
switch(zustand)
3
{
4
case 0:
5
    switch(ch)
6
    {
7
    case 'a': zustand=1; break;
8
    case 'i': zustand=41; break;
9
    case 'e': zustand=48; break;
10
    default: zustand=0;
11
    }
12
    break;
13
case 1:
14
    switch(ch)
15
    {
16
    case 'k': zustand=2; break;
17
    default: zustand=0;
18
    }
19
    break;
20
case 2:
21
    switch(ch)
22
    {
23
    case 't': zustand=3; break;
24
    default: zustand=0;
25
    }
26
    break;
27
:
28
}
an manchen Stellen an denen man was erkannt hat sind gesonderte Aktionen 
nötig, um sich zu merken, was man erkannt hat, z.B.
1
case 5:
2
    switch(ch)
3
    {
4
    case '1': aktornummer=1; zustand=6; break;
5
    case '2': aktornummer=2; zustand=7; break;
6
    default: zustand=0;
7
    }
8
    break;
9
case 10:
10
    switch(ch)
11
    {
12
    case '\r': zustand=39; break;
13
    case '0': wert=10*wert;   zustand=19; break;
14
    case '1': wert=10*wert+1; zustand=20; break;
15
    case '2': wert=10*wert+2; zustand=21; break;
16
    case '3': wert=10*wert+3; zustand=22; break;
17
    case '4': wert=10*wert+4; zustand=23; break;
18
    case '5': wert=10*wert+5; zustand=24; break;
19
    case '6': wert=10*wert+6; zustand=25; break;
20
    case '7': wert=10*wert+7; zustand=26; break;
21
    case '8': wert=10*wert+8; zustand=27; break;
22
    case '9': wert=10*wert+9; zustand=28; break;
23
    default: zustand=0;
24
    }
25
    break;
Auf die Art wird das ankommende Zeichen sofort verarbeitet, man muss 
nichts speichern ausser dem Zustand und sogenannter Attributwerte, wie 
hier aktornummer und wert, und die haben bekannte Speichergrösse.

Der ganze switch-Aufwand lässt sich stark vereinfachen als Tabelle 
'tabellengesteuerte Zustandsmaschine' oder statisch verkette Liste, und 
man hat immer die Möglichkeit, mehr Attribute und weniger Zustände 
gegeneinander aufzurechnen.

Ganze Compiler arbeiten so, und die auswertenden Programmstücke bzw. 
Tabellen werden automatisch aus der Syntax generiert.
Gast #6221520
Lesenswert?

Felix schrieb:
> aktor1 100
>
> aktor1 kann ich mittels strncmp ermitteln
> strncmp(input, "aktor1", 6)
>
> aber wie komme ich an die 100?

Nachdem die anderen dich fast vergrault haben, geb ich dir einen Rat:

Wenn du das so herum schreiben willst, dann brauchst etwas, das dir 
deine Eingabezeile auseinandernimmt, also einen Parser. Das ist nicht 
schwer, will aber erstmal getan sein.
Hier ein Beispiel dafür:
1
char match (char* item, char** Zptr)
2
{ char* P;
3
  IgnoreSpace(Zptr);
4
  P = *Zptr;
5
  if (UpCase(*P) != *item) return 0;
6
  while (*item) { if (UpCase(*P++)!=(*item++)) return 0; }
7
  *Zptr = P;
8
  IgnoreSpace(Zptr);
9
  return 1;
10
}

Die Benutzung ist leicht:
char* Cpt;
...
  if (match("DIR",&Cpt))   { DoDir(wo); return;}
  if (match("LIST",&Cpt))  { DoList(wo); return;}
  if (match("COPY",&Cpt))  { DoCopy(wo); return;}
  if (match("DEL",&Cpt))   { DoDelete(wo); return;}
na und so weiter.

In gleicher Weise kannst du dir auch einen Eingabekonverter schreiben 
für Integerzahlen. Prinzip dabei ist, daß du über das Argument char** 
Zptr den Zeiger in der Zeile weiterstellst, so daß du vom aufrufenden 
Programm her dich nicht kümmern mußt, wie lang deine Schlüsselworte sind 
und wieviele Leerzeichen dazwischen stehen.

Aber für deinen Fall würde ich das Ganze völlig anders herum 
organisieren: Nämlich eben NICHT zeilenorientiert, sondern formatfrei 
nach folgender Regel:
1. zuerst kommt das Argument als reine Integerzahl, dann kommt ein 
Kennbuchstabe für das, was du stellen willst.
2. jeder Kennbuchstabe führt nach seiner Ausführung zum Ablöschen des 
Arguments.
3. alles was dein Algorithmus nicht kennt, wird stillschweigend 
ignoriert und das eventuelle Argument gelöscht.

Beispiel:
A sei der Kennbuchstabe für Aktor 1, B sei derjenige für Aktor 2 usw.

4711A0815B
Das setzt Aktor A auf 4711 und Aktor B auf 815. Das Ganze erinnert ein 
bissel an das Gerber-Format für's Leiterplatten anfertigen.

W.S.
Gast #6221536
Lesenswert?

W.S. schrieb:
> Nachdem die anderen dich fast vergrault haben, geb ich dir einen Rat:

na so schlimm ist es noch nicht ;)

Cyblord -. schrieb:
> Du kannst atoi doch auf jeden Startpunkt im String setzen.

Da hätte ich auch drauf kommen müssen.
Habe es vorerst so gelöst. Die daten speichere ich alle im puffer, mit 
strncmp frage ich ab wonach und mit atoi hole ich mir dann den Wert.
Momentan alles noch sehr hart. Also aktor1 darf z.B. nicht akt1 
umbenannt werden, da sonst die Länge nicht mehr passt.

Michael B. schrieb:
> Üblicherweise kommen die Zeichen aus einem UART einzelzeichenweise und
> man möchte sie auch gleich verarbeiten damit man sie nicht unnötig
> speichern muss und ndafür Pufferspeicher (unbekannter Länge) reservieren
> muss.

Habe es so gelernt, dass Auswertungen nicht in einer ISR gemacht werden 
sollen.
Werde mir aber auch deine Lösung mal ansehen und versuchen umzusetzen
Gast #6221551
Lesenswert?

Felix schrieb:
> Momentan alles noch sehr hart. Also aktor1 darf z.B. nicht akt1
> umbenannt werden, da sonst die Länge nicht mehr passt.

Tja, eben.

Schreib deinen Quellcode so, daß du dich möglichst nicht auf feste 
Längen, feste Zeichenpositionen, festes groß/klein etc. selbst 
festnagelst.

Sowas ist extrem unflexibel, verbaut dir ein leichtes Erweitern, ist 
anfällig für Tippfehler auf der PC-Seite und so weiter.

W.S.
Gast #6221561
Lesenswert?

Felix schrieb:
> Habe es so gelernt, dass Auswertungen nicht in einer ISR gemacht werden
> sollen.

Das ist grundsätzlich auch richtig. Gib deinem UART-Treiber deshalb zwei 
Ringpuffer für TX und RX je einen, damit der einige Zeichen eben puffern 
kann. Normalerweise reichen für den RX Puffer 8 Zeichen völlig aus. Und 
ausgewertet wird in einer Funktion, die du von main aus aufrufst.

W.S.
(Firma: fritzler-avr.de) #6221597
Lesenswert?

W.S. schrieb:
> Nachdem die anderen dich fast vergrault haben, geb ich dir einen Rat:

Da meldet sich aber wiklich der Richtige!
Wenn hier wer Foristen dumm von der Seite anmachst dann bist du das.

W.S. schrieb:
> char match (char* item, char** Zptr)
> { char* P;
>   IgnoreSpace(Zptr);
>   P = *Zptr;
>   if (UpCase(*P) != *item) return 0;
>   while (*item) { if (UpCase(*P++)!=(*item++)) return 0; }
>   *Zptr = P;
>   IgnoreSpace(Zptr);
>   return 1;
> }

Was ist das denn jetzt schonwieder für ein Nichtskönner Code?
Schonmal was von der string.h gehört/gelesen?!

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