Ich glaube, ich habe einen Knoten im Hirn.
Parser für serielle Daten
uint16_t adr, channel, value;
printf ("%s\r\n", &frame_buffer[5]);
if (sscanf (&frame_buffer[5],"%u,%u,%u",&adr,&channel,&value)==3)
{printf ("%u,%u,%u", adr, channel, value);
if (adr==modul_adr)
{
}
}
die printf sind nur Testausgaben
Nr.1 liefert
12,1,60000<\r><\n>
das ist korrekt und entspricht den gesendeten Daten
Nr2:
0,1,60000
adr ist immer 0, egal was da gesendet wird, dementsprechend passt der
Adressvergleich natürlich nicht.
Ja, ich weiss, das Problem sitzt fast immer vor der Tastatur....
Evtl. sind vor dem eigentlichen String noch irgendwelche unsichtbaren
Steuerzeichen (z.B. "\r") im &frame_buffer[5] vorhanden, die zwar beim
printf("%s...") egal sind, dem sscanf() aber nicht schmecken?
Ne, nichts.
Das bekomme ich geliefert:
{"WR",12,1,60000}
habs mir auch mit Hterm angeschaut, da ist nichts weiter drin, auch
keine Leerzeichen.
Die gesamte Botschaft in geschweiften Klammern, '{' als Startzeichen und
wird entfernt, '}' durch 0 ersetzt in der Empfangsroutine.
Und in frame_buffer (ja, ist gross genug) steht dann wirklich
"WR",12,1,60000\0
if (!strncmpf (frame_buffer, "\"WR\",",5 )
{//hier komme ich an
}
Gast
#5776165
Die 5 für deine frame_buffer array Größe kommt mir falsch vor. Es geht doch darum, den Inhalt von frame_buffer auf die Variablen aufzuteilen, oder sehe ich das falsch? Habe das mal mit gcc in Linux gemacht:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
Es gibt dabei verschiedene Größen und Definitionen von frame_buffer. Sollte das nicht so ablaufen?
Gast
#5776166
Hier noch die Ausgaben dazu: 12,1,60000 Ergebnis sscanf: 3 W,0,1,60000 Ergebnis sscanf: 4 99,1,60000 Ergebnis sscanf: 3
Gast
#5776167
%u erwartet unsigned int, das ist aber nicht auf jedem System ein uint16_t. Versuchs's mal mit unsigned int statt uint16_t.
Gast
#5776169
pegel schrieb: > Die 5 für deine frame_buffer array Größe kommt mir falsch vor. Da ist keine Arraygröße - er startet dort an zu lesen. Auch bei mir auf dem Rechner funktioniert alles wie gewünscht:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
nur bei sscanf gab es Warnungen weil uint16_t auf meinem PC unsigned shorts sind. Also muss man da %hu nehmen (statt %u). Siehe oben.
Danke für die Mühe, ich werde es auch gleich mal mit nem anderen Compiler probieren, muss mal schauen was ich habe was liefert: char frame_buffer1[]="xx12,1,60000<\r><\n>"; res=sscanf(&frame_buffer1[2],"%u,%u,%u",&adr,&channel,&value); bei dir?
Gast
#5776171
12,1,60000 Ergebnis sscanf: 3
Gast
#5776174
H.Joachim S. schrieb: > char frame_buffer1[]="xx12,1,60000<\r><\n>"; Die drei Zahlen werden extrahiert. Egal welchen String man nimmt.
Also wohl doch der berühmte Compilerfehler? CodeVision 3.33
Gast
#5776177
> uint16_t adr, channel, value; > sscanf (&frame_buffer[5],"%u,%u,%u",&adr,&channel,&value) > Also wohl doch der berühmte Compilerfehler? Nix Compilerfehler - haben doch schon genug Leute geschrieben: %u für unsigned int, %hu für unsigned short. Deine Variante läuft nur auf Systemen mit 16-bit-ints richtig, auf allen anderen zermantscht sie den Speicher. Wenn du unbedingt uint16_t benutzen willst, musst du inttypes.h includen und dann SCNu16 als Specifier benutzen: sscanf(str, "%"SCNu16",%"SCNu16",%"SCNu16, &adr,&channel,&value); Nicht schön, aber die einzig portable Variante.
foobar schrieb: > Nicht schön, aber die einzig portable Variante. Wenn die Leute meinen, dass sie unbedingt die Typen aus stdint.h nehmen müssen, dann sollen sie auch leiden :-) Denn meist sind die einfachen Typen wie uint16_t die falsche Wahl. uint_least16_t oder uint_fast16_t sind oft besser geeignet.
Muss nicht portabel sein. Läuft auf einem AVR (Mega168) und bleibt auch dort. Bei Gelegenheit werde ich da noch mal dran gehen, habs jetzt erst mal "zu Fuss" auseinander klamüsert. Mit unsigned int und unsigned char dasselbe Verhalten der erste Teil war: if (!strncmpf (frame_buffer, "\"RD\",",5 )) {if (sscanf (&frame_buffer[5], "%u", &adr)==1) {if (adr==modul_adr) { } } } und funktioniert, mit nur einen Parameter. Bei mehr als einem ist immer der erste 0, alle folgenden sind korrekt
%u ist für unsigned int %hu ist für unsigned short %hhu ist für unsigned char (seit C99) Bei %u beschreibt scanf sizeof(int) Bytes Wenn die Variable aber weniger Bytes belegt, wird über deren Grenze hinaus geschrieben und andere Variablen überschrieben.
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.