Forum: Mikrocontroller und Digitale Elektronik scanf und NULL


von David P. (chavotronic)


Lesenswert?

Hallo,

Ich frage mit einem Mikrocontroller eine serielle Schnittstelle nach 
Werten ab und bekomme von der anderen Seite dann einen String, gefolgt 
von einem CR.
Soweit so gut. Ich möchte nun auswerten ob eventuell nur ein CR 
zurückgegeben wurde.

char str[32];
int main() {
    while (1) {
        pc.scanf ("%s",str);
         if (str[0]==0) {
          pc.printf("NULL string");
          }
          else {
           pc.printf("valid string");
           }
    }//end while 1
}

Die Ausgabe "NULL String" kommt nie, besser gesagt wenn ich nur CR 
schicke passiert gar nichts.
Woran kann das liegen?

von DirkB (Gast)


Lesenswert?

Weil scanf Whitespace (' ' \t \r \n) überliest und solange wartet, bis 
ein vernünftiges Zeichen (für %s) kommt.
Nimm besser fgets. Das liest alle Zeichen bis zum '\n'.

NULL ist für einen Leerstring nicht korrekt.

von David P. (chavotronic)


Lesenswert?

gets erkennt dann aber nicht mein CR (\r), weil es ein LF (\n) erwartet.
Problem ist es, dass das CR von einem Gerät gesendet wird, und ich keine 
Möglichkeit habe dies zu ändern.

von Karl H. (kbuchegg)


Lesenswert?

David P. schrieb:
> gets erkennt dann aber nicht mein CR (\r), weil es ein LF (\n) erwartet.
> Problem ist es, dass das CR von einem Gerät gesendet wird, und ich keine
> Möglichkeit habe dies zu ändern.

Sendet das Gerät CR LF, also beide Zeichen?

Wenn ja, dann filtert man das eben aus.

Allerdings ist es auf µC meistens sowieso nicht so schlau, printf und 
scanf zu verewnden. Meistens ist man besser bedient, wenn man sich die 
Low-Level Schreib/Lese Funktionen selber schreibt. Sind ja auch nicht 
weiter wild und ein Zeilenlesen bis zu einer Endekennung ist ja kein 
großartiges Problem. Das Beharren auf printf/scanf verkompliziert die 
Sachen meistens einfach nur.

(Auf Desktop Systemen sieht die Sache anders aus. Da hinter printf bzw 
scanf Verteiler sitzen, die zb über das Betriebssystem 
Stream-Redirections betreiben, macht dort das Verwenden von printf/scanf 
Sinn. Aber all das hat man auf einem µC ja traditionell nicht.)

von David P. (chavotronic)


Lesenswert?

Leider schickt das Gerät nur ein CR ohne LF. So wie aussieht muss ich 
die Routinen dann selbst schreiben. Wollte es nur umgehen weil ich 
dachte es sei mit scanf einfacher.
Vielen Dank!

von Karl H. (kbuchegg)


Lesenswert?

David P. schrieb:

> dachte es sei mit scanf einfacher.

Wenn du scharf darüber nachdenkst, kommst du drauf, dass das für dich 
brauchbare 'gets' in etwa so aussieht

void gets( char* string )
{
  char c;

  while( ( c = pc.getc() ) != '\r' )
    *string++ = c;

  *string = '\0';
}

Das wird an Einfachheit von scanf schwer zu schlagen sein :-)

OK. Mit vernünftiger Fehlerbehandlung wirds dann noch etwas 
komplizierter, aber scanf hat genau das gleiche Problem. Im Kern ist das 
schon deine Funktionalität. Da lohnt es nicht, großartige Klimmzüge mit 
scanf zu machen :-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

David P. schrieb:
> Wollte es nur umgehen weil ich
> dachte es sei mit scanf einfacher.

Naja, ein wenig Kanonen auf Spatzen. ;-)

Es müsste mit dem %[-Format gehen, so in der Art
1
scanf("%20[^\r]%*c", &array);

Das %*c überliest dabei das folgende \r.

von Peter D. (peda)


Lesenswert?

Man sollte nie direkt von der UART lesen, da dann die CPU steht und 
nichts anderes machen kann.

Besser richtet man einen FIFO ein, der per Interrupt die UART einliest. 
Und dann kann man auch gleich ein Flag setzen, wenn CR oder LF empfangen 
wurde.

Und das Main liest erst aus dem FIFO, wenn das Flag gesetzt wurde, d.h. 
der String komplett ist.


Peter

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.