Hallo Forum,
ich habe ein Problem mit folgender switch-case Anweisung:
1
switch(Befehl){
2
case'D':
3
uart_puts("ein D\r");
4
break;
5
case'R':
6
uart_puts("ein R\r");
7
break;
8
case'W':
9
uart_puts("ein W\r");
10
break;
11
case'P':
12
uart_puts("ein P\r");
13
break;
14
default:
15
uart_puts("nop\r");
16
break;
17
}
In 'Befehl' steht ein Zeichen, welches ich über RS232 mit meinem
ATMega88 empfange. Je nach empfangenem Zeichen wird eine Antwort über
RS232 an den PC gesendet (mit der UART library von P. Fleury).
Das ganze funktioniert auch sehr gut.
Nun habe ich neu den default-Zweig eingefügt. Wenn jetzt ein ungueltiges
Zeiche empfangen wird, soll ein 'nop' gesendet werden - funktioniert
auch.
ABER: Wenn ein gültiges Zeichen empfangen wird (D, R, W oder P) wird
neben dem zugehörigen Text auch immer noch das 'nop' aus dem default
Zweig gesendet.
Nach meinem Verständnis soll der default Zweig aber nur durchlaufen
werden, wenn keine andere Bedingung erfüllt ist, und nicht bei jeder
richtigen UND falschen Bedingung.
Ist das ein Kompilerfehler oder habe ich einen Fehler zwischen den
Ohren?
Wie erreiche ich, dass der default Zweig NUR bei ungültigen Zeichen
durchlaufen wird?
P.S.
Ich verwende avr-gcc (WinAVR 20080610) 4.3.0
Das sieht eher nach einem Problem in der Datenübertragung aus. Z.b.
verwendet dein Terminal 9 Bit, statt 8. o.ä. so dass dein µC denkt, es
würde 2 Zeichen empfangen. setze mal dort an...
Zum debuggen: Einfach mal vor das Switch ein:
Jede Wette du empfängst in Wirklichkeit nicht 1 Zeichen sondern 2. Zb
ein abschliessendes Return nach dem Buchstaben.
Lass dir doch einfach mal den 'Befehlsbuchstaben' zurückgeben (als
Zeichen und zusätzlich den ASCII Code in Zahlenform) dann siehst du was
dein Programm wirklich zu Gesicht bekommt.
Ich bin immer wieder erstaunt, das fast alle Kompilerfehler von
Anfängern gefunden werden...
Oder ist es vielleicht doch einfach nur die Selbstüberschätzung der
Anfänger, die immer zuerst dem Kompiler die Schuld geben?
Klaus schrieb:
> Oder ist es vielleicht doch einfach nur die Selbstüberschätzung der> Anfänger, die immer zuerst dem Kompiler die Schuld geben?
Ich unterstelle niemandem in dem Bereich eine böse Absicht.
Es ist einfach der Lernprozess, dass unser vermeintlich gut
funktionierendes Gehirn ganz schnell den Überblick über vermeintlich
einfache Abläufe verliert.
> Ich bin immer wieder erstaunt, das fast alle Kompilerfehler von> Anfängern gefunden werden...
@Klaus
OK, ich bin nicht der Profi, und habe auch nicht wirklich an einen
Kompilierfehler geglaubt. Die echten Fehler des Kompilers sind bestimmt
nicht von so einfacher Natur. Darum auch das '?'. Dafür kann ich besser
Minigolf ;-)
@Sven, K-H.
Richtig, ich sende nicht nur ein Zeichen sondern eine Zeichenkette mit
abschießendem 'CR' (ist die Ende Kennung). Zusammen bis zu 4 Zeichen
(das CR mitgezählt.
Die Routine wird eigentlich aber erst aufgerufen, wenn die Ende Kennung
gefunden wurde (so hofft der Anfänger).
Ich werde eure Tipps mal verfolgen. Danke schon mal. Ist echt gut, dass
einige von euch hier auf andere Bäume hinweisen, wenn mann den Wald
nicht mehr sieht.... Wobei ich auch immer für eine spitzfindige
Bemerkung offen bin.
MfG
Matthias
Karl heinz Buchegger schrieb:
> Jede Wette du empfängst in Wirklichkeit nicht 1 Zeichen sondern 2. Zb> ein abschliessendes Return nach dem Buchstaben.
Vor der Switch Anweisung kopiere ich mir das erste Zeichen des Strings
in die Variable 'Befehl':
1
Befehl=String[0];// erstet Zeichen aus dem String holen
2
Parameter1=String[1];// zweites Zeichen aus dem String holen
3
4
switch(Befehl){
5
...sieheoben...
6
}
der default Zweig wird aber wie beschrieben durchlaufen.
matsch
Matthias R. schrieb:
> Ich werde eure Tipps mal verfolgen.
Der Haupttip ist immer:
Spick dein Programm mit Ausgaben. Wenn du nicht weißt, warum eine
bestimmte Aktion ausgelöst wird, dann mach vor den entscheidenden if
(oder in deinem Fall switch) eine Ausgabe rein, die dir den
'Entscheidungsträger' anzeigt.
In deinem Fall hätte sich auch angeboten ...
1
default:
2
uart_putc("->'");
3
uart_putc(Befehl);
4
uart_putc("'");
5
uart_puts("nop\r");
6
break;
... damit du nicht nur siehst, dass etwas nicht verarbeitbares in den
Verteiler gekommen ist, sondern auch noch siehst was das den war.
Bei einer 'Fehlermeldung' ist es immer gut, den Auslöser auch mit
auszugeben. Die Anzahl der von Micorosoft mit der simplen Fehlermeldung
in die Verzweiflung getriebenen Programmierer "Eine DLL konnte nicht
gefunden werden" ist legendär .... Verdammt - WELCHE?
Matthias R. schrieb:
> der default Zweig wird aber wie beschrieben durchlaufen.
Der ganze switch-case wird dann aber wahrscheinlich in einer
übergeordneten Schleifenstruktur ein zweites mal aufgerufen.
Mach mal folgendes:
Karl heinz Buchegger schrieb:
> ... sondern auch noch siehst was das den war.
Danke für den Tipp, den Fehler mit auszugeben.
Die Funktion wurde tatsächlich immer zwei mal aufgerufen. Fehler
erkannt, gefunden, behoben ... und der Anfänger hat sogar das 'warum'
verstanden.
Danke
Matsch
(nein) (ich) (bin) (kein) schrieb:
> versuche es mit einem lokalen funktionsblock, also {} nach jedem case>>> quasi case 'a': {//weil hier mehr als ein Befehl kommt}
So ein Quatsch!
das mit dem "Kompilerfehler" im Betreff ist schon richtig...
Auf keine andere Weise kriegt man im GCC-Forum so schnell gute und
fundierte Antworten.
Mit dem Betreff "Wie funktioniert default: in switch" wären nur
haufenweise Antworten wie "Kauf dir ein C-Buch" gekommen
Eine eigene Frage?
Dieser Thread ist über 17 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.