switch - case probléma

 ( Jedite | 2005. március 11., péntek - 14:02 )

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Hm!

Köszönöm a sok jótanácsot.

A struktúrával pedig nincs baj.
Amit én ide beírtam az csak a header file-ban lévő deklaráció.
Magát a structúrát a main-ben hozom létre a:
struct config config;
sorral.

Szóval azal tényleg nincs probléma.

Ami tényleg probléma volt, hogy hülye voltam és elfelejtettem, hogy a switch - case-nek csak konstans értéket lehet megadni. :-(

Úgyhogy leváltottam az egészet if-es alakra.

Most már működik!

Azért köszönöm mindenkinek a fáradozást.
És elnézést kérek, hogy nem voltam, az elején igazán egyértelmű.

:o

Üdvözletem.

Az alábbi volna a problémám:

Írok egy apró Ncurses alapú kígyó játékot.
Mecsináltam, hogy a felhasználó home könyvtárába csináljon egy rejtet könyvtárat egy config file-al, amibe menti a konfigurációt.
A beállítások egyenlőre csak az irányító billentyűkre terjednek ki, és azok is csak karakter gombok lehetnek (semmi spec egyenlőre).

Ezt egy:

struct config
{
char left;
char right;
char up;
char down;
};

Struktúrában tárolom.

Miután beolvasom a file-ból a beállításokat. Átpaszollom a struktúrát a fő függvénynek, ami irányítja, kirajzolja, stb... a kígyót.

a mozgás egy while(1) végtelen ciklusban van, amiben egy switch utasítás mondja meg paramétertől függően, hogy merre menyjen a kígyó.

char a "lastdir" változó típusa

switch (lastdir)
{
case config.up :
{
ypos -= 1;

if(ypos < 1)
ypos = (ymax);

break;
}
case config.down :
{
ypos += 1;

if( ypos > ymax )
ypos = 1;

break;
}
case config.left :
{
xpos -= 1;

if( xpos < 1 )
xpos = xmax;

break;
}
case config.right :
{
xpos += 1;

if( xpos > xmax )
xpos = 1;

break;
}
}

A problémám az, hogy az alábbi hibaüzenetet dobálja a gcc fordításkor minden egyes case utasításra:
case label does not reduce to an integer constant

próbáltam típus változtatással is: (int)config.left
de úgy se ment.

Segítségeteket előre is kösz!

switch ((int)lastdir) { ....... :wink:

[quote:5b37ca50ea="zelenat"]switch ((int)lastdir) { ....... :wink:[/quote:5b37ca50ea]

ufff

Ez igazán egyszerűnek hangzik.

Csak még annyi érdekelne, hogy cast-olás nélkül, mikor még nem csináltam meg a struktúrát, akkor csak simán:

switch (lastdir)
{
case 'a':
...
case 'd':
...
}

volt megadva. És úgy nem kelett a lastdir változót mahinálni.
Most miért kell?

Ezt ha kifejtenéd röviden. Ha meg nem lehet röviden és van időd, akkor hosszan.

Köszönöm!
:o

Bocsi, ... lehet... , hogy elneztem es nem jo amit irtam. :oops:

Ha emigy mukodott akkor valoszinu, hogy a structura def. nem tetszik neki.

Talan igy:

struct _config_{
...
...
}config;

[quote:c5b5969206="zelenat"]Bocsi, ... lehet... , hogy elneztem es nem jo amit irtam. :oops:

Ha emigy mukodott akkor valoszinu, hogy a structura def. nem tetszik neki.

Talan igy:

struct _config_{
...
...
}config;[/quote:c5b5969206]

Sajnos nem azon a gépen vagyok amin ki tudnám próbálni, úgyhogy majd meglátjuk.

A struktúra deffiniálásával nem hinném, hogy gond volna.

Én inkább arra tippelek, hogy struktúra tagjainak az értékadásánál lehet talán gond.

Egy read() függvénnyel egy buffer[]-be mentem a config file adatait, majd abból kiveszem a megfelelő karaktereket. példa:

config.left = buffer[i]

A gond inkább az lehet, hogy a switch - case páros nem úgy kezeli a :

switch (lastdir)
case config.left :
....

megadást, mint a:

switch (lastdir)
case 'a' :
....

És nem tudom miért, már össze vissza cast-oltam mindent.
:cry:

.......:oops: :oops: Na ez nem az ;n napom. Ezer Bocs,de a case konstanssal dolgozik. Hasznalj if -et.

[quote:5237440aba="zelenat"].......:oops: :oops: Na ez nem az ;n napom. Ezer Bocs,de a case konstanssal dolgozik. Hasznalj if -et.[/quote:5237440aba]

Próbáltam már azzal is, csak azzal meg el sem indul a függvény. Úgyhogy nem is tudom úy igazán, hogy hól lehet a gond.

Én legfőképpen az értékadásra tippelek.

[code:1:9b5b0c077c]
switch (lastdir)
{
case 'k':
ypos -= 1;
if (ypos < 1) ypos = ymax;
break;

case 'j':
ypos += 1;
if (ypos > ymax) ypos = 1;
break;

case 'h':
xpos -= 1;
if (xpos < 1) xpos = xmax;
break;

case 'l':
xpos += 1;
if (xpos > xmax) xpos = 1;
break;
}
[/code:1:9b5b0c077c]
Ahogy látom, pascal-szerűen 1-től max-ig kezeled a pozíciókat. Nem lehetséges, hogy 0-tól (max-1)-ig kellene, és ez így valahol off-by-one hibát csinál?

Összevont típus és változódeklarációt (amit csináltál) nem érdemes erőltetni, se kisebb, se gyorsabb nem lesz tőle, max. áttekinthetetlenebb. Inkább így valahogy:
[code:1:9b5b0c077c]
/* definialunk strukturat */
struct config_struktura
{
char up, down, left, right;
};

/* pelda: ebbol a tipusbol egy valtozo */
struct config_struktura cfg0;
/* na ezt irtad 'struct config_struktura {...} cfg0;'-nak osszevonva */

/* hogy ne kelljen mindenhol a 'struct'-ot kiirni */
typedef struct config_struktura config_tipus;
/* persze ezt is lehet osszevonva: typedef struct config_struktura {...} config_tipus; */

/* es ebbol egy valtozo: */
config_tipus cfg1;
[/code:1:9b5b0c077c]

Másik, érdemes debuggolás céljából a beolvasott értékeket rögtön kiíratni az stderr-re, pl.:
[code:1:9b5b0c077c]
int fd;
char buf[1024];
size_t lng;
config_tipus cfg1;

lng=read(fd, buf, 1024);
if (lng<0) fprintf(stderr, "nem tudtam olvasni, mindjart elszallok!\n");
buf[lng] = '\0'; /* stringkent fogom kiiratni, le kell zarni */
fprintf(stderr, "Ezt olvastam: '%s'\n", buf);
cfg1.up = buf[0];
fprintf(stderr, "a felfele kodja: '%c'\n", cfg1.up);
/* stb. */
[/code:1:9b5b0c077c]

És egy jó tanács: ne kapkodj, ne varázsolj, ne tippelj, castolgass balra-jobbra, csak még jobban belegabalyodsz. A számítógéped is determinisztikus, a nyelv is, a fordító is, úgyhogy mindennek oka van, amit meg kell érteni először, és csak utána "javítani". Bár a C híres arról, hogy nem azt a hibát jelzi, ahol elrontottad, hanem [i:9b5b0c077c]azt, ahonnan már a legnagyobb jóindulattal sem lehet szintaktikailag értelmezni[/i:9b5b0c077c], az első hibaüzenet esetében ez általában megegyezik :).

keves lovesem van a c-hez, de:
-case-nek integer tipus kell, ezert nem mukodik az alap char-os verzioval
- a case 'a' -nal szerintem a c a karaktert integerkent ertelmezi, mint altalaban, igy azert mukodik

mivel nem sok jelentoseget latom, hogy a structurad char legyen, egyszerusitened, ha integer lenne alapbol szvsz

ha hulyeseget irtam, javitsatok nyugottan:-)

Amint azt már [i:698f56b403]zelenat[/i:698f56b403] is megírta a hiba ott rejtőzik, hogy a case kulcsszó után egy konstans értéket vár a C. Ergo változót nem használhatsz case labelként.
Próbáld inkább így:
[code:1:698f56b403]
if (lastdir == config.up) {
ypos -= 1;
if (ypos < 1) {
ypos = ymax;
}
} else if (lastdir == config.down) {
ypos += 1;
if (ypos > ymax) {
ypos = 1;
}
} else if (lastdir == config.left) {
xpos -= 1;
if (xpos < 1) {
xpos = xmax;
}
} else if (lastdir == config.right) {
xpos += 1;
if (xpos > xmax) {
xpos = 1;
}
} /* else handle error */
[/code:1:698f56b403]
És ha már jótanácsoknál tartunk, akkor hadd adjak én is egyet: ha ilyen fordítási hibád van (mármint, hogy nem teljesen tiszta, hogy mi is a probléma), akkor érdemes a problémás részletből egy kis példakódot gyártani, majd azt lefordíttatni a [url=http://www.comeaucomputing.com/tryitout/]Comeau online fordítójával[/url]. A visszaadott hibaüzenetek a legtöbb esetben sokkal érthetőbbek, mint a többi fordítóé, és a fordító teljesen a szabvány szerint működik (még a hibaüzenetekben is a szabványra hivatkozik...)

[quote:a893a42b63="Jedite"]A struktúra deffiniálásával nem hinném, hogy gond volna.[/quote:a893a42b63]
Pedig ott is gond van.

[quote:cc01f45896="andrash"][quote:cc01f45896="Jedite"]A struktúra deffiniálásával nem hinném, hogy gond volna.[/quote:cc01f45896]
Pedig ott is gond van.[/quote:cc01f45896]

Bizony!

A "config" nem maga a structura, hanem a structura típusa!
Nincs strukturád!

Helyesen:

struct config {char right; char left; char up;char down;} CRSR;

CRSR.right=key1;CRSR.left=key2;CRSR.up=key3;CRSR.down=key4;
switch (key)
{
case CRSR.right: valami1();break;
case CRSR.left: valami2();break;
case CRSR.up: valami3();break;
case CRSR.down: valami4();break;
default: break;
}

Szóval én a beküldött problémát és így kezelném le.

[quote:165bf7c0e0="meditor"]switch (key)
{
case CRSR.right: valami1();break;
case CRSR.left: valami2();break;
case CRSR.up: valami3();break;
case CRSR.down: valami4();break;
default: break;
}
[/quote:165bf7c0e0]
Nem jó így sem, a case-hez csak konstans kifejezést írhatsz, változó nem lehet címke. Szóval if-el kell.

[quote:9d6ff6be90="Skuzzy"]keves lovesem van a c-hez, de:
-case-nek integer tipus kell, ezert nem mukodik az alap char-os verzioval
[/quote:9d6ff6be90]
A char is integer típus, nevezetesen 8 bites előjeles egész. A switch-nek pedig bármilyen egész jó, szélességtől és előjelességtől függetlenül:
[code:1:9d6ff6be90]
#include <stdio.h>

int main(void)
{
unsigned short q = getchar();
switch (q)
{
case 'a': printf("ez A\n"); break;
case 'b': printf("ez B\n"); break;
default: printf("ez valami mas\n"); break;
}
return 0;
}

fules@rasta:/tmp$ vim swcase.c
fules@rasta:/tmp$ gcc -Wall -o swcase swcase.c
fules@rasta:/tmp$ ./swcase
b
ez B
[/code:1:9d6ff6be90]

[quote:5fac2213bc="andrash"][quote:5fac2213bc="meditor"]switch (key)
{
case CRSR.right: valami1();break;
case CRSR.left: valami2();break;
case CRSR.up: valami3();break;
case CRSR.down: valami4();break;
default: break;
}
[/quote:5fac2213bc]
Nem jó így sem, a case-hez csak konstans kifejezést írhatsz, változó nem lehet címke. Szóval if-el kell.[/quote:5fac2213bc]

Hát persze, igazad van! Bocs... Tanulság: ha kiteszel valamit,
előtte fordíts (-::