Zu blöd für sscanf?

#5776129
Lesenswert?

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....
#5776154
Lesenswert?

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
Lesenswert?

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?
Gast #5776169
Lesenswert?

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.
Gast #5776177
Lesenswert?

> 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.
#5776353
Lesenswert?

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

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