Forum: Mikrocontroller und Digitale Elektronik sscanf kurze Hilfe


von Alex (Gast)


Lesenswert?

Guten Morgen,

bin schon 2 Tage am verzweifeln. Ganzes Internet durchsucht finde den 
Fehler nicht :(

InputData[0] ist "cmd save 2 9" und wird auch richtig eingelesen.
1
char data2;
2
char data3;
3
char cmd[8];
4
char dataa [8];
5
6
7
if (4 == sscanf(InputData[0], "%3c %4c %1d %1d", cmd, dataa, &data2, &data3)) {
8
  if ((strcmp(cmd,"cmd")==0) && (strcmp(dataa,"save")==0){
9
  //unwichtig
10
  }
Wenn ich die Variablen auslese, steht das drin:
cmd = "cmd" ->OK
dataa = "save" ->OK
data2 = 0 -> FALSCH
data3 = 9 -> OK

Wo liegt das Problem?

Danke schön

von Karl H. (kbuchegg)


Lesenswert?

Alex schrieb:

> Wenn ich die Variablen auslese, steht das drin:
> cmd = "cmd" ->OK
> dataa = "save" ->OK
> data2 = 0 -> FALSCH
> data3 = 9 -> OK
>
> Wo liegt das Problem?

Das einen Formatangabe von %d nicht zu einem char passt.
1
int data2;
2
int data3;

von Alex (Gast)


Lesenswert?

DANKE!
hat auf Anhieb funktioniert :)
Hat mich irritiert, dass data3 IMMER richtig ausgegeben wurde.

von Karl H. (kbuchegg)


Lesenswert?

Mit den Formatangaben scheinst du übrhaupt ein wenig auf Kriegsfuss zu 
stehen. Deine %c Angaben für die String-Anteile sind auch nicht koscher.
Das sollten eigentlich %s sein und als Zahl gibst du die maximal 
erlaubte Anzahl an Zeichen für diesen String an. Also nicht die Anzahl 
der Character die du erwartest (in deinem Fall 3), sondern die Anzahl 
der Character, die du in deinem Argument (das Array cmd) unterbringen 
kannst. Das sind in deinem Fall 7, weil du ja auch noch 1 Zeichen für 
die Stringterminierung \0 brauchst.

Mittels %3c hast du keinen String eingelesen. Dass die strcpy gut gehen, 
ist eher zufällig, weil in deinem Array vorher schon lauter 0-Bytes 
drinnen waren, die zufällig als String-Terminierung fungieren. %c liest 
Character und keine Strings, hängt also keine String-Terminierung an das 
Ergebnis an.
1
int data2;
2
int data3;
3
char cmd[8];
4
char dataa [8];
5
6
7
if (4 == sscanf(InputData[0], "%7s %7s %d %d", cmd, dataa, &data2, &data3)) {
8
  if ((strcmp(cmd,"cmd")==0) && (strcmp(dataa,"save")==0){
9
  //unwichtig
10
  }

Die 1 bei %1d sparst du dir lieber. Wenn data2 nicht größer als 9 sein 
darf, dann prüfst du das im nachhinein ab und gibst eine entsprechende 
Fehlermeldung, die den Benutzer darauf hinweist, dass dieser Wert nicht 
größer als 9 sein darf. Sich da im Vorhhinein einzuschränken ist nicht 
sehr schlau. Solange alles gut geht und die auszuwertenden Daten auch 
der erwarteten Vorgabe entsprechen ist das alles kein Problem. Zum 
Problem wird es erst, wenn dem nicht so ist. Und da muss man dann auch 
sagen, dass es mit scanf schon recht schwer ist, ausser einem 
nichtssagendem 'Fehler in der Eingabe' eine vernünftige und 
aussagekräftige Fehlermeldung zu generieren, mit der man als 
Aussenstehender auch was anfangen kann und die einem einen Hinweis 
darüber gibt, was eigentlich das Problem ist.
Nichts gegen scanf. Aber wenn es darum geht, einen von einem 
menschlichen Benutzer stammenden String auseinander zu nehmen, würde ich 
es nicht nehmen.

von Decius (Gast)


Lesenswert?

Fehlt in der Zeile nicht noch was?:

if (4 == sscanf(InputData[0], "%3c %4c %1d %1d", cmd, dataa, &data2,...

Müsste es nicht wie folgt heissen?:

if (4 == sscanf(&InputData[0], "%3c %4c %1d %1d", cmd, dataa, &data2,...

oder:
if (4 == sscanf(InputData, "%3c %4c %1d %1d", cmd, dataa, &data2,...

von Decius (Gast)


Lesenswert?

Hab gerade nachgesehen. Ja sscanf erwartet an der Stelle von InputData 
einen Pointer. InputData[0] ist aber kein Pointer.

--> Adressoperator benutzen "&InputData[0]"
--> oder den Index weglassen "InputData"

von Karl H. (kbuchegg)


Lesenswert?

Decius schrieb:
> Hab gerade nachgesehen. Ja sscanf erwartet an der Stelle von InputData
> einen Pointer. InputData[0] ist aber kein Pointer.

Sagt wer?

Wir wissen nicht, was sich hinter InputData versteckt.

Disclaimer: Es kann natürlich sein, dass du recht hast. Ich denke sogar, 
es ist recht wahrscheinlich, dass du recht hast. Aber solange nicht klar 
ist, was InputData tatsächlich darstellt, ist das Spekulation. Es könnte 
ja auch ein
1
char* InputData[10];   // Ringbuffer aus 10 Strings. Die UART allokiert für
2
                       // für jede eingehende Zeile einen neuen String und
3
                       // legt ihn hier ab
sein.
Es könnte auch ein
1
char InputData[2][20];  // 2 Strings a 20 Zeichen für Double Buffering
sein.

von Decius (Gast)


Lesenswert?

Ja stimmt Karl-Heinz. Naja, hatte eben die "Standardlösung" im Kopf. :-)

von Karl H. (kbuchegg)


Lesenswert?

Decius schrieb:
> Ja stimmt Karl-Heinz. Naja, hatte eben die "Standardlösung" im Kopf. :-)

Im Zweifel für den Angeklagten :-)
Der Compiler hätte ihm schon was gesagt, wenn er versucht einen char als 
Funktionsargument zu übergeben, wo ein const char* erwartet wird.

von Andreas D. (rackandboneman)


Lesenswert?

"Das einen Formatangabe von %d nicht zu einem char passt."

Nicht nur dass... je nach Umgebung kann einem sowas den Stack umpflügen 
und zu sehr abstrusen Effekten führen - zB dass andere Variablen 
überschrieben werden oder sogar der Programmablauf durcheinandergerät 
weil Rücksprungaddressen verändert werden....

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.