Hallo, ich bin gerade dabei, in WinAVR mit der scanf Funktion herumzuexperimentieren mit folgendem Code in der main loop (mit fdevopen wurden printf und scanf auf den UART gelenkt): int iTestvar; while(1) { scanf("%d", iTestvar); printf("%d\n\r", iTestvar); } Eine per Hyperterminal eingegebene Dezimalzahl soll also wieder zurück ans Hyperterminal gesendet werden. Das funktioniert mit Dezimalzahlen auch prima, sobald ich allerdings ein ungültiges Zeichen wie z.B. 'g' eintippe, dann wird ständig die ASCII-Ziffer '0' ans Hyperterminal gesendet. Soweit ich weiss, bricht scanf bei einem ungültigen Zeichen ab, soweit ok, aber warum wird dann beim nächsten scanf nicht wieder gewartet, bis ein Zeichen vorhanden ist? cu, Max
Weil es per Standard an der Stelle aufhören muss zu scannen, an der es einen Konvertierungsfehler gab. Wenn du nun an der gleichen Stelle weitermachst, gibt's natürlich wieder den gleichen Konvertierungsfehler. Du solltest einfach die Fehlerauswertung durchführen.
scanf("%d", iTestvar); Das geht nicht bzw. wird interessante Auswirkungen haben. Aufgrund des Formatstringes erwartet scanf nämlich einen Pointer auf int. Was Du aber übergibst ist ein int. Der wird wie ein Pointer behandelt, und je nachdem, welchen Wert der int hat, wird also irgendwo in den Speicher geschrieben. scanf("%d", &iTestvar); sollte sinnvollere Resultate liefern.
Danke für die Antworten. Den Adressoperator & vor iTestvar bei scanf habe ich verwendet, das war ein Tippfehler beim Schreiben des Beitrags. Ohne & würde das ja auch mit gültigen Dezimalzahlen nicht funktionieren. Wie funktioniert das mit der Fehlerauswertung genau? Als Rückgabewert wird doch die Anzahl der eingelesenen Zeichen zurückgeliefert, richtig? Woher "weiß" scanf beim nächsten Aufruf, dass zuvor ein fehlerhaftes Zeichen eingegeben wurde? cu, max
hallo ! aus langjähriger erfahrung mit scanf: ich würde einen bogen drum machen, wenn es irgendwie geht. auch in windows-software verzichte ich lieber drauf, auch wenn es bei float variablen so verlockend ist. ist übrigens nicht nur meine meinung. michael
Das Problem liegt hier daran, daß scanf den Eingabepuffer nicht löscht. Sinnvoller als scanf ist meines Erachtens nach die Kombination aus gets (was eine komplette Zeile einliest) und sscanf. Vor dem Aufruf von sscanf kann eine einfache Plausibilitätsprüfung erfolgen (wurden überhaupt genügend Zeichen eingegeben?). Wenn es nur darum geht, einen numerischen Wert einzulesen, ist gets in Kombination mit atoi/atof sicherlich eine zuverlässigere Lösung.
Ich würde auch fgets + sscanf bevorzugen (nicht gets, weil man da keine Kontrolle hat, dass der Nutzer den Puffer nicht überlaufen lassen kann). Ansonsten: jede beliebige Beschreibung von scanf in einem beliebigen C-Buch lesen. scanf gibt die Anzahl der durchgeführten Konvertierungen zurück, im obigen Fehlerfalle also wohl eine 0.
Ich möchte nochmal auf den ürsprünglichen Code zurück kommen, weil das Thema noch nicht so ganz verstanden habe. Mein mißratener Code sieht so aus: int number; int main(void) { // initialize the serial port initserial(); // switch LED on DDRB |= (1<<PB2); PORTB &= ~(1<<PB2); // mail loop while (1) { printf("Enter a number\r\n"); scanf("%d",&number); printf("You entered: %d\r\n",number); } } Problem 1: Sobald ich einen Buchstaben eingebe, scheint das Programm abzustürzen und sich selbst zu zerstören. Denn nach Strom aus und wieder an geht nichtmal die LED an. Ich muss dann den Controller neu flashen. Und das passiert immer, 100% reproduzierbar. Was ist denn hier falsch? Problem 2: Wenn ich die Deklaration der Variable "number" in die main Methode hinein verschiebe, wartet scanf nicht auf meine Eingabe, sondern die Schleife wiedeholt sich endlos und gibt irgendeine negative Zahl aus. Ich tippe jetzt mal auf Stack Fehler, bin mir mir aber nicht im Klaren, wodurch ich den produziert haben könnte. Die Zeilen von initserial() und den Funktionen zum senden und empfangen habe ich nämlich 1:1 der glibc-Doku entnommen. Problem 3: Wenn scanf im Fehlerfall den Eingabepuffer nicht leert, wie kann ich das dann "manuell" tun?
Stefan Frings wrote:
> Ich möchte nochmal auf den ürsprünglichen Code zurück kommen, ...
Nein, bitte nicht nach 4 Jahren. Bitte mach einen neuen Thread auf.
Auch wenn das Problem gleich klingt, ist es meistens was komplett
anderes.
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.