Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Taulukon alustaminen

Sivun loppuun

ristokor [07.02.2006 18:39:31]

#

Tulipa tässä matopeliä tehdessä pari probleemaa.

Eli, minulla on tietue, jossa on kaksi int taulukkoa ja niitä ei ole alustettu. Haluaisin alustaa ne myöhemmin samalla tavalla, kuin ne yleensä alussa alustetaan, mutta se ei onnistunut: Eli koodi (muutettu tilanteeseen sopivaksi):

struct LEVEL
{
      int x[];   //x koordinaatit. (pitääkö asettaa
                 //tilanvaraus vai mikä se onkaan jo tässä vaiheessa? vrt. x[3];
      int y[];   //y koordinaatit.
};
...   //jatkuu kunnes...

LEVEL level[10];   //10 level tietuetta.

level[0].x[10]={200,220,240,260};   //Ei toimi näin!! vaan pitää tehdä näin: level[0].x[0]=200, level[0].x[1]=220, ja niin edespäin.

Tämä on varsin hankalaa kun koodi kasvaa hirmuisesti, kun pitää erikseen kaikki alustaa. Pystyykö sitä alustamaan kuten tuo toimimaton alustus. Ja x ja y koordinaatit kuvaavat mihin kohtaan este piirretään myöhemmässä funktiossa jossa myös on vikaa. Eli koodi (muutettu tilanteeseen sopivaksi):

void setlevel (LEVEL p_level[])   //funktio saa parametrina tietuetaulukon tietueen.
{
    draw (este, tausta, p_level[].x[kerta], p_level[].y[kerta]);  //piirtää taustaan, esteen, kohtaan level[].x ja level[].y, kerta tulee yhdestä laskukaavasta.
}

Ongelma on siinä, että kun funktio saa parametrikseen level tietueen niin kääntäjä valittaa kohdassa p_level[].x[kerta],että p_level[] pitäisi osoittaa johonkin tietueeseen, mutta kun funktiolle annetaan joka kerta eri tietue niin eihän se sitten toimi jos laittaa vaikkapa p_level[0]. Miten tuon saisi ratkaistua.

Vielä, että sitten kun pelini joskus valmistuu ja haluaisin sen tänne arvosteltavaksi, niin laitanko minä sen keskusteluun vai koodivinkkeihin?

Metabolix [07.02.2006 18:50:41]

#

En tosiaan ymmärtänyt, mitä tuolla ensimmäisellä hait. Mutta joko asetat taulun koon tuossa kohti tai sitten tutustut new- ja delete-operaattoreihin tai malloc- ja free-funktioihin. Ja en näe mitään syytä, miksi tuo arvojen asettaminen toimisi noin. Totta kai ne pitää asetella yksitellen. Mutta toisaalta ei ole mitään järkeä asetella tason arvoja ohjelman sisällä, vaan ne kuuluu ladata tiedostosta.

Mitä ihmettä nuo kaikki tyhjät hakasulut ovat olevinaan? Opettele käyttämään osoittimia. Ja taas kerran oli niin epämääräinen selitys, ettei siitä oikein ottanut selvää.

Koodivinkkeihin älä missään nimessä mitään ohjelmaa laita, kun se ei kuitenkaan ole koodivinkki. Laita jonnekin nettiin (tai lähetä jollekulle, joka omistaa kotisivut) ja laita keskusteluun linkki.

On todella hankala auttaa, kun on vain kasa toimimatonta koodia ja epämääräisiä ajatuksia, mitä sillä pitäisi tehdä. Selkeämpi selostus olisi tosiaan paikallaan, ja auttaisi myös tietää, mitä missäkin rakenteessa pitäisi olla ja miten niitä yrität käyttää.

ristokor [07.02.2006 19:05:49]

#

:D Arvasin, että on sekavaa, mutta en oikein osannut selittää. Uusi yritys.
Toki ei ole ongelma vaikka laittaisinkin näin: x[3];

Hietasen oppaasta (on edelleenkin lainassa) jäi epäselväksi se miten tehdään oma nimi.h tiedosto. (eli siis se mikä includetetaan: #include "nimi.h") (en kyllä kirjaa loppuun ole lukenutkaan)

Ja sitten tuo funktiojuttu. Eli tyhjät hakasulut ovat sen takia kun en tiedä miten pitäisi toteuttaa ennalta tietämättömän, parametrina annetun taulukon alkion (eli siis tietueen) kutsu. Jos osoittimilla niin tuleeko se jotenkin p_level[*] vai miten?

T.M. [07.02.2006 19:06:07]

#

level[0].x[10]={200,220,240,260};

Jos yhtään taulukoita osaan, niin eikös tuon pitäisi olla:

level[0].x={200,220,240,260};

Tai sitten x[] tjsp.

ristokor [07.02.2006 19:11:35]

#

T.M.: Ei toiminut.

Metabolix [07.02.2006 19:13:33]

#

Ihan tekstieditorilla noita tiedostoja yleensä tehdään ^^.

typedef struct __LEVEL
{
  int x[4], y[4];
} LEVEL;

void funktio(LEVEL * lev)
{
  lev->x[1] = 1;
}

LEVEL taso[10];

int main(void)
{
  taso[2].x[0] = 10;
  funktio(&taso[2]);
  printf("taso[2].x[1] == %i\n", taso[2].x[1]); /* Se on 1 */
  return 0;
}

Ja taulukkoon ei edelleenkään voi asettaa arvoja aaltosuluissa muulloin kuin alustusvaiheessa.

ristokor [07.02.2006 19:25:33]

#

Onko tuolla typedef structilla ja kahdella alaviivalla jotain merkitystä?

Ja sitten:

Metabolix kirjoitti:

void funktio(LEVEL * lev)
{
  lev->x[1] = 1;
}

Tässä ei minulla ollut tarkoitus asettaa x:n arvoksi mitään, mutta se p_level[]. Siinä on se ongelma. Eli sen arvo on tässä vielä tuntematon, koska se annetaan vasta funktiokutsussa esim. setlevel(p_level2); , joten mikä osoitin, viittaus, mikälie, pitää asettaa p_level[]:n sijasta, ts. tyhjien hakasulkujen sijasta.

Sain kuin sainkin toimimaan. Eli toimi täysin Metabolixin ohjeen mukaisesti, jäi vain piste poistamatta.
Kiitos!!

zorm [08.02.2006 19:11:32]

#

Kertokaapas vielä tuon LEVEL -structin kahden alaviivan merkitys! :D
Se alkoi minuakin mietityttää.

Blaze [08.02.2006 19:16:10]

#

Siinä määritellään structi nimeltä __LEVEL, jolle samalla annetaan vaihtoehtoinen nimi (LEVEL) typedefillä.

Minä oon tavannu jättää tuon ensimmäisen nimeämisen kokonaan pois, kun siitä ei oo mitään hyötyä, ts. suoraan

typedef struct {
    int x[4], y[4];
} LEVEL;

koo [08.02.2006 21:02:45]

#

Tuo alaviiva-alaviiva-jotakin on huono juttu sen takia, että tuollaiset nimet on varattu kääntäjä- ja kirjastototeutusta varten, eivätkä tavalliset kuolevaiset sellaisia saisi käyttää.

typedef-hässäkkä on C-mäinen kiertotie sille, ettei joka paikassa tarvitsisi kirjoittaa struct-sanaa, sormethan siinä kuluu. Alaviivaviritys on oikeastaan turha, samaan tulokseen pääsee ihan laillisesti kirjoittelemalla

typedef struct LEVEL
{
        int x[4], y[4];
} LEVEL;

sillä nuo tunnukset menevät vähän niin kuin eri lokeroon C:n sisällä.

Tuota ekaa LEVEL-sanaa (tai __LEVEL) ei ole oikein voinut jättää pois, jos struct sisältää viittauksen itseensä, kun se viittaus on pitänyt tehdä struct-sanan avulla joka tapauksessa.

C++:ssa asia on aina ollut vähän toisin, siellä tuota typedefiä ei tarvitse tuossa muutoinkaan.

Blaze [08.02.2006 23:05:35]

#

koo kirjoitti:

Tuota ekaa LEVEL-sanaa (tai __LEVEL) ei ole oikein voinut jättää pois, jos struct sisältää viittauksen itseensä, kun se viittaus on pitänyt tehdä struct-sanan avulla joka tapauksessa.

Ah, melkein arvasinki, että siitä oli jotain haittaa. Noh, hyvä tietää.

ristokor [09.02.2006 15:13:21]

#

Nyt tein tiedoston jossa on esitelty tietue LEVEL, ja samassa tiedostossa on vielä luotu kaksi tietuetta. Olen sisällyttänyt ne pääohjelmaan, mutta kun yritän käyttää luotuja tietueita niin se ei onnistu. Itse veikkaisin virheen olevan siinä, että kun normaalisti tietueet luodaan main() ohjelmassa niin nyt kun ne ovat eri paikassa niin ei toimikaan. Pitäisikö tässä käyttää osoittimia?

Metabolix [09.02.2006 18:14:17]

#

Tiedän kyllä, että se on C:tä, mutta missäpä sanottiinkaan, että tämä olisi ollut C++:aa? Tiedä koskaan, mitä roskaa Windowsin epästandardit C-kääntäjät päästävät lävitseen... Ja jos kaksi alaviivaa häiritsevät, niin ainahan siihen voi laittaa vaikkapa jonkin kirjaimen eteen. Sitten taas muistaakseni VC++ ei tykännyt, jos laittoi saman nimen (voin muistaa väärinkin).

ristokor: Mikä virhe tulee ja missä vaiheessa?

ristokor [09.02.2006 19:18:07]

#

Funktion parametreina yritän antaa level.h tiedostossa olevaa tietuetaulukon tietuetta. (Muutin tilanteeseen sopivaksi: setlevel(&level[1]);
Käännosvaiheessa tulee tällainen virhe:

-In function 'int SDL_main(int, char**)';
-'level' undeclared (first use this function)
-(Each undeclared identifier is reported only once for each function it appears in.)
[Build Error] [main.o] Error1

Metabolix [09.02.2006 19:44:22]

#

Muuttujia ei ikinä alusteta otsikkotiedostoissa! Vaikka onhan sekin mahdollista sinänsä. Mutta olet joka tapauksessa onnistunut tekemään jonkin mokan. Ilmeisesti taulukkosi nimi ei ole 'level'.

ristokor [09.02.2006 19:53:54]

#

Jaa eli ei otsikkotiedostoissa. Täytyykö ne sitten kirjoittaa jollain ohjelmalla vaikkapa binääritiedostoon ja sitten ladata ne pääohjelmalla?
En huomannut virhettä nimissä, voiko se johtua siitä että ne muuttujat on eri int main() ohjelmassa?

koo [09.02.2006 21:31:13]

#

ristokor:
Sinulla taitaa olla ongelmia ihan perusjuttujen kanssa, mutta jeesaaminen on tosi hankalaa, kun selostuksesi ovat vähän epätarkkoja etkä pahemmin näytä sitä ongelmallista koodia. Homman pitäisi kuitenkin toimia tähän malliin:

esim.h:
struct LEVEL
{
        int x[4];
        int y[4];
};

void setlevel(struct LEVEL *level);

/* jos tarvii globaalia taulukkoa, niin sitten vaikka näin: */
extern struct LEVEL level[10];

esim.c:
#include "esim.h"
/* jos taulukko ei olekaan globaali, niin rivin alkuun static */
struct LEVEL level[10] = { /* alkuarvot tänne */ };

int main()
{
        setlevel(&level[2]);
}

Metabolix:
Alaviivoilla alkavien tunnusten kuuluukin mennä kääntäjästä läpi, mutta ne on varattu standardikirjaston ja kääntäjän omaan käyttöön. Häiritsee siis suunnilleen saman verran, kuin jos ryhtyisi itse määrittelemään errno-nimisiä juttuja koodissaan, eli ei välttämättä pätkääkään. :-)

Voi olla, että Microsoftin C++-kääntäjä on joskus urputtanut, jos tuota C-kikkaa on käyttänyt ja tunnukset ovat olleet samat; en tiedä. C++-standardi nyt kuitenkin jaksaa ihan erikseen mainita, että typedef-nimi saa olla sama kuin ko. luokan nimi.

Alaviivakäytäntö varmaankin juontaa juurensa jostakin tosi esihistoriallisesta C-käytännöstä ajalta, jolloin C:n nimiavaruuskäsittely ei ollut vielä standardoitu.

Metabolix [09.02.2006 23:17:58]

#

Tarkoitinkin henkistä häiritsemistä :) Tietenkin ne menevät kääntäjästä läpi, en minä niitä muuten olisi tuonne kirjoittanut.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta