PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : switch und case



Spurius
22.10.2005, 16:02
Hallo,
wie kann ich folgenden Code schreiben, ohne die Fehlermeldung

servo.c:140: error: duplicate case value
servo.c:138: error: previously used here
servo.c:146: error: duplicate case value
servo.c:144: error: previously used here
servo.c:152: error: duplicate case value
servo.c:150: error: previously used here
servo.c:154: error: duplicate case value
servo.c:148: error: previously used here

zu erhalten?




if(i<=50)
{
switch(i)
{
case 1 | 2| 3| 4 | 5 : sektor[0] += get_adc(0);

case 6 | 7| 8| 9 | 10 : sektor[1] += get_adc(0);

case 11 | 12| 13 | 14 | 15 : sektor[2] += get_adc(0);

case 16 | 17| 18 | 19 | 20 : sektor[3] += get_adc(0);

case 21 | 22| 23 | 24 | 25 : sektor[4] += get_adc(0);

case 26 | 27| 28 | 29 | 30 : sektor[5] += get_adc(0);

case 31 | 32| 33 | 34 | 35 : sektor[6] += get_adc(0);

case 36 | 37| 38 | 39 | 40 : sektor[7] += get_adc(0);

case 41 | 42| 43 | 44 | 45 : sektor[8] += get_adc(0);

case 46 | 47| 48 | 49 | 50 : sektor[9] += get_adc(0);

}
for(j=0;j<10;j++)
{
sektor[j] = sektor[j] / 5;
}
waitms(100);
servo_goto(i++);
itoa(sektor[j], p_test2, 10);
send_string(p_test2);
}

Gruß
Martin

nk7
22.10.2005, 19:13
Hallo,
ich glaube der Compiler mag nach den case-Anweisungen jeweils nur einen Wert. Man könnte i durch 5 teilen

switch((i-1)/5)
{
case 0: sektor[0] += get_adc(0);
case 1: sektor[1] += get_adc(0);
...


In Deinem Beispiel ginge es sogar ohne switch/case:
if(i<=50 && i >0)
{
sektor[(i-1)/5] += get_adc(0);
}

Das ist jetzt trocken so hingeschrieben, müsste aber (zumindest fast) richtig sein.

nk7

Cathrel
22.10.2005, 20:40
Folgendes ist nicht ANSI-C kompatibel:


case 1 | 2| 3| 4 | 5 :

Was du machen könntest wäre folgendes, wobei bei linearen Werten eine andere Lösung vorzuziehen wäre.

Lösung mit switch:


case 1:
case 2:
case 3:
case 4:
case 5:
sektor[0] += get_adc(0);
break; //Achtung Break nur, wenn hier aus der switch- Anweisung gesprungen werden soll.


Ach ja, meinst du mit | das bitweise Oder oder das logische oder(||) ?

Vogon
22.10.2005, 20:46
Obwohl mir der Vorschlag von @nk7 besser gefällt, habe ich mal in den Kernighan+Ritchie geschaut. Das sollte so aussehen:


switch(i)
{
case 1 :
case 2 :
case 3 :
case 4 :
case 5 : sektor[0] += get_adc(0); break;
case 6 :
case 7 :
case 8 :
case 9 :
case 10 : sektor[1] += get_adc(0); break;

usw

SprinterSB
22.10.2005, 22:55
Folgendes ist nicht ANSI-C kompatibel:


case 1 | 2| 3| 4 | 5 :

Hehe, lustigerweise ist das sogar ANSI-C, aber nicht das, was der OP im Sinn hatte. 1 | 2| 3| 4 | 5 ist eine Konstante, die zur Compilezeit ausgewertet werden kann, wie es nach einem case sein muss. Hier in dem Fall kommt 7 raus. Das 'duplucate case value' im original-Beitrag kommt nicht durch die Veroderung von Konstanten, sondern weil die Oder-Werte zur gleichen Konstante auswerten, und im Endeffekt so was dasteht:

case 31: ....
case 31: ....

was den Fehler gibt.
Teuflich, wenn alle Ausdrücke andere Werte gehabt hätte, da hätte sich Spurius ewig gewundert, warum sein Programm nicht geht...

Ob man über (i-1)/5 geht oder ein case ist Geschmackssache und ob man die Priorität bei Codegröße oder Geschwindigkeit (da ist case besser) legt.

Spurius
24.10.2005, 17:37
Hallo,
ich versuche das jetzt so zu lösen:


for(;;)
{

char test[] = "Wert in Sektor\n\r";
char *p_test = test;
char test2[] = "hallo!\n\r";
char *p_test2 = test2;

for(i=1;i<51;i++)
{
if((i>0) & (i<=5))
{
sektor[1] += get_adc(0);
}
if((i>5) & (i<=10))
{
sektor[2] += get_adc(0);

}
if((i>10) & (i<=15))
{
sektor[3] += get_adc(0);

}
if((i>15) & (i<=20))
{
sektor[4] += get_adc(0);

}
if((i>20) & (i<=25))
{
sektor[5] += get_adc(0);

}
if((i>25) & (i<=30))
{
sektor[6] += get_adc(0);

}
if((i>30) & (i<=35))
{
sektor[7] += get_adc(0);

}
if((i>35) & (i<=40))
{
sektor[8] += get_adc(0);

}
if((i>40) & (i<=45))
{
sektor[9] += get_adc(0);

}
if((i>45) & (i<=50))
{
sektor[10] += get_adc(0);

}

waitms(200);
servo_goto(i++);
}
for(j=1;j<=10;j++)
{
sektor_2[j] = sektor[j] / 5;
*p_test2 = 0;
itoa(sektor_2[j], p_test2, 10);
send_string(p_test2);
send_string(p_test);

waitms(1000);
}
waitms(3000);
i=0;
j=0;
sektor[j] = 0;
sektor_2[j] = 0;
}
}

Leider habe ich das Gefühl, dass da noch irgendwo der Wurm drin ist.
Eigentlich sollte der ADC-Wert jeweils in den zugehörigen Sektor geschrieben werden, und nachher sollten die 10 Sektoren alle durch 5 geteilt werden, so dass ich jeweils einen Mittelwert herausbekomme.
Ich bekomme jedoch Werte >1024, sodass das nicht stimmen kann. Der letzte Wert beträgt immer 200, da ist also auch was faul.
Ich hoffe ihr könnt mir helfen, vllt. ist der Fehler ja auch nur ein kleiner Fehler, der ich als C-Anfänger nicht finde.
Gruß
Martin

Spurius
26.10.2005, 13:44
Immer noch nicht gelöst...

PicNick
26.10.2005, 14:04
Denk an den Unterschied "&" und "&&" . Da liegen schlaflose Nächte dazwischen.

Spurius
26.10.2005, 14:19
Hallo,
habs geändert, geht aber tortzdem nicht richtig. Die Werte sind teilweise immer noch größer als 1024 und der letzte ist wieder 200.

SprinterSB
26.10.2005, 14:54
Die Werte von sektoe[] solltest du zurücksetzen, bevor du was draufaddierst, nicht danach.
Hast du dran gedacht, daß die Indizes bei sektor[N] von 0..N-1 laufen, und nicht von 1..N?

Spurius
26.10.2005, 15:45
Hi,
hier der aktuelle Code:


int8_t i = 0;
int8_t j = 1;
int8_t k = 0;
for(;;)
{
char test[] = "Wert in Sektor\n\r";
char *p_test = test;
char test2[] = "hallo!\n\r";
char *p_test2 = test2;


for(k=0;k<=9;k++)
{
sektor[k] = 0;
sektor_2[k] = 0;
}
for(i=1;i<51;i++)
{
if((i>0) && (i<=5))
{1
sektor[0] += get_adc(0);
}
if((i>5) && (i<=10))
{
sektor[1] += get_adc(0);

}
if((i>10) && (i<=15))
{
sektor[2] += get_adc(0);

}
if((i>15) && (i<=20))
{
sektor[3] += get_adc(0);

}
if((i>20) && (i<=25))
{
sektor[4] += get_adc(0);

}
if((i>25) && (i<=30))
{
sektor[5] += get_adc(0);

}
if((i>30) && (i<=35))
{
sektor[6] += get_adc(0);

}
if((i>35) && (i<=40))
{
sektor[7] += get_adc(0);
}
if((i>40) && (i<=45))
{
sektor[8] += get_adc(0);

}
if((i>45) && (i<=50))
{
sektor[9] += get_adc(0);

}

waitms(100);
servo_goto(i);
}

for(j=0;j<=9;j++)
{
sektor_2[j] = sektor[j] / 5;
*p_test2 = 0;
itoa(sektor_2[j], p_test2, 10);
send_string(p_test2);
send_string(p_test);
waitms(1000);
}
waitms(3000);
}
}


Die sektor-Variablen sind so sektor[9] bzw sektor_2[9] deklariert.
@Sprinter Ich habe versucht deine Tips zu umzusetzen, aber es geht dennoch nicht, der letzte Wert ist weiterhin 200 und die Werte davor >1024, wobei ich das Gefühl habe, dass sie ansteigen.

Spurius
26.10.2005, 16:04
Hallo nochmal,
also das eine Problem ist gelöst, ich habe in der ADC-Routine davor 4mal in eine variable geschrieben und danach gemittelt, jetzt schreibe ich 10-mal in die Variable und es kommen passable Ergebnisse raus, ich weiss aber nicht warum das genau so ist. Vllt hats was mit timing zu tun.
Das jetzige Problem ist noch, dass der letzte Bereich immer 200 liefert.
Wenn ich jedoch das waitms()

for(j=0;j<=9;j++)
{
sektor_2[j] = sektor[j] / 5;
*p_test2 = 0;
itoa(sektor_2[j], p_test2, 10);
send_string(p_test2);
send_string(p_test);
waitms(1000);
}

verändere, verändert isch auch der letzte Wert, er bleibt jedoch immer konstant, er scheint mit der wartezeit zusammenzuhängen.[/code]

SprinterSB
26.10.2005, 16:42
Die sektor-Variablen sind so sektor[9] bzw sektor_2[9] deklariert.

Die Deklaration muss lauten
<typ> sektor[10];
weil du 10 Werte im Feld hast, nämlich von 0..9.

Informatiker am Bahnhof: "Null, eins, zwei, ... Wo ist mein dritter Koffer??!!"