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 }
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 | #include "stdio.h" |
2 | |
3 | int main() |
4 | {
|
5 | unsigned int adr, channel, value; |
6 | char s1; |
7 | int res; |
8 | |
9 | char frame_buffer1[]="12,1,60000<\r><\n>"; |
10 | res=sscanf(frame_buffer1,"%u,%u,%u",&adr,&channel,&value); |
11 | printf ("\n%u,%u,%u\n", adr, channel, value); |
12 | printf ("Ergebnis sscanf: %d\n\n",res); |
13 | |
14 | char frame_buffer2[20]={"W,0,1,60000,0x70"}; |
15 | res=sscanf(frame_buffer2,"%c,%u,%u,%u",&s1,&adr,&channel,&value); |
16 | printf ("%c,%u,%u,%u\n", s1, adr, channel, value); |
17 | printf ("Ergebnis sscanf: %d\n\n",res); |
18 | |
19 | char frame_buffer3[]="99,1,60000<\r><\n>"; |
20 | res=sscanf(frame_buffer3,"%u,%u,%u",&adr,&channel,&value); |
21 | printf ("\n%u,%u,%u\n", adr, channel, value); |
22 | printf ("Ergebnis sscanf: %d\n\n\n",res); |
23 | }
|
Es gibt dabei verschiedene Größen und Definitionen von frame_buffer. Sollte das nicht so ablaufen?
Hier noch die Ausgaben dazu: 12,1,60000 Ergebnis sscanf: 3 W,0,1,60000 Ergebnis sscanf: 4 99,1,60000 Ergebnis sscanf: 3
%u erwartet unsigned int, das ist aber nicht auf jedem System ein uint16_t. Versuchs's mal mit unsigned int statt uint16_t.
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 | #include <stdio.h> |
2 | #include <stdint.h> |
3 | |
4 | int main () |
5 | {
|
6 | |
7 | char frame_buffer[]="\"WR\",12,1,60000, 42 und viel mehr"; |
8 | |
9 | uint16_t adr, channel, value; |
10 | |
11 | printf ("ausgabe 1: %s\r\n", &frame_buffer[5]); |
12 | |
13 | |
14 | if (sscanf (&frame_buffer[5],"%hu, %hu, %hu" ,&adr,&channel,&value)==3) |
15 | {
|
16 | printf ("ausgabe 2: %u, %u, %u", adr, channel, value); |
17 | |
18 | }
|
19 | |
20 | return 0; |
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?
H.Joachim S. schrieb: > char frame_buffer1[]="xx12,1,60000<\r><\n>"; Die drei Zahlen werden extrahiert. Egal welchen String man nimmt.
> 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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.