Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Taulukkoapua

Meitsi [05.01.2006 13:38:36]

#

Pitäis saada nuo tileInfoTable ja tileDataTable taulukoiksi, yhden alkion kokoisiksi. Miten pitäis menetellä? Tämäs siksi, jotta memcpy toimii... niin ainakin #ohjelmointiputka:lla sanottiin.

#define MPL_SUCCESS 1
#define MPL_FILE_NOT_FOUND 2
#define MPL_SYNTAX_ERROR 3
#define MPL_MISSING_TILE 4

struct Tile{
    int X;
    int Y;
    int Width;
    int Height;
    bool Solid;
    unsigned int HitTop;
    unsigned int HitBottom;
    unsigned int HitLeft;
    unsigned int HitRight;
    char Name[256];
    char Filename[256];
};
struct TileData{
    char Name[256];
    SDL_Surface *Data;
};

Tile *tileInfoTable;
TileData *tileDataTable;

int LoadMap(char filename[255]) {
    FILE *tiedosto;
    tiedosto = fopen(filename, "r");
    if (tiedosto!=NULL) {

        // TÄSSÄ PITÄIS SAADA NOI tileInfoTable ja tileDataTable yhen alkion kokosiks tauluiks, mite onnistuu? Datan menetyksellä ei ole väliä koska tässä kohtaa kumminkin pitäisi tyhjentää nuo taulut.

        char rivi[256];
        bool tiledef, tiledefStarted, tiledefBracketStarted, mapdef, mapdefStarted, mapdefBracketStarted;
        tiledef=tiledefStarted=mapdef=mapdefStarted=tiledefBracketStarted=mapdefBracketStarted=false;
        while(!feof(tiedosto)) {
            fgets(rivi, 255, tiedosto);
            if ((strcmp(rivi, "TILEDEF") == 0) && tiledefStarted == false) {
                tiledefStarted=true;
            } else if (tiledefStarted == true && (strcmp(rivi, "{") == 0)) {
                tiledefBracketStarted=true;
            } else if (tiledefBracketStarted == true && (strcmp(rivi, "}") == 0)) {
                tiledefBracketStarted=tiledefStarted=false;
                tiledef=true;
            } else if (tiledefBracketStarted == true) {
                int vanhakoko;
                vanhakoko = sizeof(tileInfoTable) / sizeof(Tile);
                Tile *uusi = new Tile[vanhakoko+1];
                memcpy(uusi, tileInfoTable, vanhakoko * sizeof(Tile));
                delete[] tileInfoTable;
                tileInfoTable = uusi;

                TileData *uusi2 = new TileData[vanhakoko+1];
                memcpy(uusi2, tileDataTable, vanhakoko * sizeof(TileData));
                delete[] tileDataTable;
                tileDataTable = uusi2;

                sscanf(rivi, "\"%s\" \"%s\"", &tileInfoTable[vanhakoko]->Name);
                // kesken...

            } else {
                return MPL_SYNTAX_ERROR;
            }
        }
    } else {
        return MPL_FILE_NOT_FOUND;
    }
    return MPL_SUCCESS;
}

/*
int CheckHit(Tile lahde, Tile kohde) {
    int lahdeX2 = lahde.X + lahde.Width;
    int lahdeY2 = lahde.Y + lahde.Height;
    int kohdeX2 = kohde.X + kohde.Width;
}*/

/*

<thefox> square35, uusi=new paska[uusikoko];memcpy(uusi,vanha,vanhakoko);delete[] vanha;vanha=uusi;
<thefox> (kun uusikoko>vanhakoko)
<thefox> memcpy(uusi,vanha,vanhakoko*sizeof(paska)) tietysti pitäis olla
*/

Metabolix [05.01.2006 19:13:21]

#

Ei, ei ja ei; memcpy haluaa osoittimen. Taulukko on vain silmänlumetta :)

Tile Yksi_Tile;
Tile * Tile_Ptr = new Tile;

// Muistin kohtaan &Yksi_Tile kopioidaan kohdasta Tile_Ptr sizeof(Tile) tavua.
memcpy(&Yksi_Tile, Tile_Ptr, sizeof(Tile));

Siis osoitin siihen kohti muistia, mihin kopioidaan, ja siihen, mistä kopioidaan, ja lopuksi kopioitavien tavujen määrä.

CyberianRat [06.01.2006 02:54:02]

#

Hmmm... nyt pitää olla varovainen (Jos sovelletaan Metabolixin esimerkkiä suoraan tuohon ohjelmaan), ettei tule käytettyä delete[]-operaattoria vapauttamaan muistia, joka pitäisi vapauttaa deletellä.

Jos nyt käsitin asiaa alkuunkaan, niin mikäs vika tästä puuttuu:

tileInfoTable = new Tile[1];

Tietysti pitää kutsua välillä delete[]:ä, jos tuota ajetaan monta kertaa.

Meitsi [06.01.2006 11:16:28]

#

Muuttelin systeemiä eilenillalla aika paljon, ja koodi on nyt tällainen:

#define MPL_SUCCESS 1
#define MPL_FILE_NOT_FOUND 2
#define MPL_SYNTAX_ERROR 3
#define MPL_MISSING_TILE 4

struct TilePlacement{
    int X;
    int Y;
    int ID;
};

struct TileData{
    int solid;
    SDL_Surface *Data;
};

TileData *tileDataTaulu = NULL;
TilePlacement *tilePlacementTaulu = NULL;

int LoadMap(char filename[255]) {
    if (tileDataTaulu){free(tileDataTaulu);tileDataTaulu=0;}
    if (tilePlacementTaulu){free(tilePlacementTaulu);tilePlacementTaulu=0;}
    FILE *tiedosto;
    tiedosto = fopen(filename, "r");
    if (tiedosto!=NULL) {
        char rivi[256];
        bool tiledata=false, mapdata=false, tiledim=false, mapdim=false;
        unsigned int tileamount, mapSizeX, mapSizeY, menossa=0;
        while(!feof(tiedosto)) {
            fgets(rivi, 255, tiedosto);
            int paikka = 0;
            while (paikka < 255) {
                if (rivi[paikka] == '\r') {
                    rivi[paikka] = '\0';
                } else if (rivi[paikka] == '\n') {
                    rivi[paikka] = '\0';
                }
                ++paikka;
            }
            std::cout << "Rivi luettu!" << std::endl;
            std::cout << "\"" << rivi << "\"" << std::endl;
            if (strcmp(rivi, "TILEDATA") == 0) {
                tiledata=true;
                std::cout << "Tiledata alkoi!" << std::endl;
            } else if (tiledata == true) {
                if (strcmp(rivi, "MAPDATA") == 0) {
                    tiledata = false;
                    mapdata = true;
                    std::cout << "Mapdata alkoi!" << std::endl;
                } else if (tiledim == false) {
                    sscanf(rivi, "%d", &tileamount);
                    std::cout << "tilemäärä: " << tileamount << std::endl;
                    tileDataTaulu = (TileData *) realloc(tileDataTaulu, tileamount * sizeof(TileData));
                    tiledim=true;
                    std::cout << "Suurennettiin tiletaulu." << std::endl;
                } else if (tiledim == true) {
                    char filu[256];
                    sscanf(rivi, "%s %d", &filu, &tileDataTaulu[menossa].solid);
                    tileDataTaulu[menossa].Data = SDL_LoadBMP(filu);
                    if (tileDataTaulu[menossa].Data == NULL) {
                        return MPL_MISSING_TILE;
                    }
                    std::cout << "Menossa: " << menossa << std::endl;
                    std::cout << "Ladattiin tile: " << filu << std::endl;
                    ++menossa;
                }
            } else if (mapdata == true) {

            }
            rivi[0] = '\0';
        }
    } else {
        return MPL_FILE_NOT_FOUND;
    }
    return MPL_SUCCESS;
}

void tyhjennaMuisti(void) {
    free(tileDataTaulu);
    free(tilePlacementTaulu);
}

/*
int CheckHit(Tile lahde, Tile kohde) {
    int lahdeX2 = lahde.X + lahde.Width;
    int lahdeY2 = lahde.Y + lahde.Height;
    int kohdeX2 = kohde.X + kohde.Width;
}*/

/*
<Metabolix> Tyyppi * Taulu = (Tyyppi *) malloc(Taulun_Koko * sizeof(Tyyppi));
<Metabolix> Taulu = (Tyyppi *) realloc(Taulu, Uusi_Koko * sizeof(Tyyppi));
<Metabolix> free(Taulu);
*/

EDIT: Tuo toimii ainakin mielestäni ihan oikein.

CyberianRat [07.01.2006 01:33:18]

#

Elikkä olet siirtynyt C-tyyliseen muistinvaraukseen. Käyhän se noinkin, ainakin niin kauan kun TilePlacementillä ja TileDatalla ei tarvitse olla konstruktoria eikä destruktoria, niitä kun ei free ja realloc kutsu.

Metabolix [07.01.2006 04:04:13]

#

Sen verran vielä, että jos tuossa C++-tyyliin siirtyisi ja tarvitsisi niitä konstruktoreita, niin jatkuva new-memcpy-delete kutsuisi paljon turhia kutsuja. Jokin STL-container, esimerkiksi vector, voisi olla harkittava ajatus.

Vastaus

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

Tietoa sivustosta