C++ 2d dinamikus tömb oszlop növelése

Címkék
C++ 2d dinamikus tömb oszlop növelése
2020-10-30T17:29:11+01:00
2020-10-31T11:50:20+01:00
2022-08-11T22:40:33+02:00
kokohun
Sziasztok!

Adott egy készülő RPG játék conio.h-val megoldva.
A "térkép" egy dupla mutatós tömbként van megoldva.
Kérdésem, hogy hogy lehetne megoldani hogy az utolsó oszlop-hoz + 1 oszlop hozzáadódjon az adott funkció meghívásakor? (Tudom-tudom, van erre std::vector és hasonlók, de engem ez a manuális megoldás érdekelne)

A kód: char** Map::increaseMap() { char** newMap = new char* [AREA_SIZE_X + 1]; - Pastebin.com

Ezzel próbálkoztam, de eddig nem sok sikerrel, ha futtatom lefagy a cmd. Hogy el lehessen képzelni, csatoltam egy képet is, a teli karakterek a fal objectek, a kör a player, a pont karakterek pedig pálya.
Válaszokat előre is köszönöm!

Mutasd a teljes hozzászólást!
Csatolt állomány
szerk: közben látom, hogy azt a részt javítottad, de még mindig túlcímzel, mikor newMap(i)(AREA_SIZE_Y) = '.';
az első index 0, tehát az utolsó index AREA_SIZE_Y - 1.

egyetértek IWolf88-cal, értelmetlen ezt a pointeres megközelítést erőltetni, mert rossz is, és olyan szinten bonyolítja el NEKED a dolgokat, hogy nem tudod megoldani egyedül. (tehát nem is tanulsz belőle, és minden szempontból csak hátrányai vannak)
Mutasd a teljes hozzászólást!

  • 5. newMap = new char[AREA_SIZE_Y]; ... 11. newMap[AREA_SIZE_Y++] = '.';
    Nekem úgy tűnik, hogy a newMap-et sikerült túlindexelni: AREA_SIZE_Y-1 a legmagasabb lehetséges indexe, de itt az AREA_SIZE_Y. elemet írod.
    Mutasd a teljes hozzászólást!
  • Köszönöm! Valóban eggyel el volt csúszva az index, illetve a
    delete[] map[i]
    -t kivettem és így most működik, viszont program lefutásának végeztekor így most memória errort kapok. Gondolom mivel a newMap nincs felszabadítva. Próbáltam így
    return map
    előtt/után:

    for (int i = 0; i < AREA_SIZE_X; i++) { delete[] newMap[i]; } delete[] newMap;
    De sajnos nem jött be.
    Mutasd a teljes hozzászólást!
  • Pedig ennek jónak kell lennie:
    delete[] map[i]
    Illetve még egy hiba:

    3. for (int i = 0; i < AREA_SIZE_X; ++i) 4. { 5. newMap = new char[AREA_SIZE_Y]; 6. for (int j = 0; j < AREA_SIZE_Y; ++j) 7. { 8. newMap[j] = map[j]; 9. } 10. delete[] map; 11. newMap[AREA_SIZE_Y++] = '.'; 12. }
    11. sor után az AREA_SIZE_Y értéke egyel nagyobb lesz, vagyis ha a külső ciklus "fordul egyet", a belső for előtti "new char[AREA_SIZE_Y]" is már ezzel az új mérettel allokál. Emiatt a ciklusban a

    8. newMap[j] = map[j];
    kifejezés is okozhat túlindexelést.

    Érdemes lenne mondjuk std::cout-tal kiíratnod a változók értékét, hogy lásd, hogy hol mikor mi történik, vagy debuggerrel nézd végig lépésről lépésre, hogy mit csinál a kód amit írtál (nemtudom milyen IDE-t használsz).
    Így látatlanban, vaktában próbálgatásokkal nagyon körülményes lesz a program megírása, és nem is lehet belőle tapasztalatot sem szerezni, mivel nem látod, hogy _pontosan_ mi történik.
    Írasd ki a változókat!
    Mutasd a teljes hozzászólást!
  • Az indexelés már jó volt az elsőírásod után, igaz én ezt nem közöltem veled. Így néz ki jelenleg a fv.-em: char** Map::increaseMap() { char** newMap = new char* [AREA_SIZE_X + 1]; - Pastebin.com

    Igen, a változókat azokat már debuggoltam, csak nem jöttem rá magamtól. De a felszabadítással nem oké valami továbbra sem és továbbra is a newMap-re gondolok mert futás után memory error-t kapok. A
    delete[] map[i]
    -t ha beírom a külső ciklusba akkor szintén memória error-t kapok. Indexeket checkoltam, az első írásod óta úgy működik ahogy szerettem volna, úgy működik ahogy kell, de a felszabadítással valami nem oké. Destruktor szabadítja fel egyébként amely így néz ki:

    ~Map() { for (int i = 0; i < AREA_SIZE_X; i++) { delete[] map
    ; } delete[] map; }
    De ugye ez csak a map-et szabadítja fel, de ez eddig ezelőtt a fv-em előtt hibátlanul működött, ezért gondolom hogy ez nem lehet hibás. Ezért gondolom hogy a newMap felszabadításával van valami, de aztán lehet tévedek.

    Mutasd a teljes hozzászólást!
  • az a gond, hogy az area_size_y a ciklus végére area_size_y + area_size_x lesz, és mikor kilépéskor a destruktorban végigmész a pointereiden, túlindexeled. :D
    annyiból jó amúgy, hogy ezt az értelmetlenül nyakatekert megoldást erőlteted, hogy így a saját bőrödön megtapasztalhatod, amit a másik posztodnál említettem: a felesleges komplexitás végig fog kísérteni a teljes fejlesztés alatt. feleslegesen több hibalehetőség, feleslegesen alacsonyabb teljesítmény, feleslegesen nagyobb memóriahasználat.
    Mutasd a teljes hozzászólást!
  • Edit: for ciklusban
    delete[] map[i]
    Nagyon nem szeret engem ez a kódos formázás :'D
    Mutasd a teljes hozzászólást!
  • szerk: közben látom, hogy azt a részt javítottad, de még mindig túlcímzel, mikor newMap(i)(AREA_SIZE_Y) = '.';
    az első index 0, tehát az utolsó index AREA_SIZE_Y - 1.

    egyetértek IWolf88-cal, értelmetlen ezt a pointeres megközelítést erőltetni, mert rossz is, és olyan szinten bonyolítja el NEKED a dolgokat, hogy nem tudod megoldani egyedül. (tehát nem is tanulsz belőle, és minden szempontból csak hátrányai vannak)
    Mutasd a teljes hozzászólást!
  • Vagy ha mégis ragaszkodsz a C-s tömbözéshez, akkor tegyél be index ellenőrzéseket, tényleg, egyből látni fogod, hogy hol ment félre a program (std::vector-nál ha a vector<T>::operator[] helyett vector<T>::at-ot használsz az megcsinálja neked). Ezen a szinten még az assertek is hasznosak lehetnek.

    A delete pedig megint egy trükkös jószág: egyáltalán nem biztos, hogy az okozza a gondot, lehet, hogy az csak előhozza. Dinamikus memóriakezelés ilyen formában nem egy biztonságos dolog, ilyenkor tényleg bármi megtörténhet. Lehet, hogy gond nélkül lefut a program lehet, hogy A helyen száll el, de az is lehet, hogy B-n, az is lehet, hogy csak késleltetve okoz gondot egy félreeső helyen.
    Mutasd a teljes hozzászólást!
  • Bingó! Köszönöm! Mindig ilyen apró dolgokon megy el sajnos a figyelmem. Én is egyetértek veled és IWolf88-al, de sajnos egyetemen ezt követelik meg tőlem. Én is csinálnám legszívesebben std::vectorral stb. de ha órán/vizsgán nem használhatom... hát ja, rá vagyok kényszerítve ezekre sajnos. Annyi kérdésem még lenne hogy itt a newMapet a függvényen belül szükséges egyáltalán felszabadítani? Vagy? (Gondolom ha fv híváskor nem is, de program futás végénél 1x legalább kell)
    Mutasd a teljes hozzászólást!
  • pont ott hozod létre, miért szabadítanád fel? :)
    a félreértés ott lehet, hogy amikor átadod egy változó értékét a másiknak (map = newMap) csak pointereket adogatsz át, de a new-val azt a területet foglaltad le, ahová ezek mutatnak. tehát nem akarod felszabadítani, csak amikor már nem használod magát a területet.
    a kulturált megoldás egyébként az lenne, ha kiemelnéd a map létrehozás és megszüntetés funkciókat (amik eredetileg voltak is), és amikor átméretezel, akkor is ezeket a függvényeket alkalmaznád. (és konstruktor/destruktorban is!) így ha egyszer megírod jól ezt a két függvényt (ahogy kell), akkor később nem futnál bele megint ebbe az allokációs gondba :D
    Mutasd a teljes hozzászólást!
  • btw ez az "AREA_SIZE_Y++;" önmagában még mindig túlcímzéshez fog vezetni, mert nem foglaltál ennyivel nagyobb területet előtte, és a függvényhívás után mindenhol úgy fogod látni, mintha eggyel nagyobb lenne, ami nem igaz.
    + gondolom az area_size_x -et is növelni akarod... :)
    Mutasd a teljes hozzászólást!
  • Igen, tapasztaltam. Véglegesen erre jutottam:
    char** Map::increaseMap() { char** newMap = new char* [AREA_SIZE_X + 1]; - Pastebin.com

    Szerk.: Igen, majd szeretném, de ugye csak egyszerre egy irányba, mert ugye az input is egyszerre egy gombnyomás.
    Mutasd a teljes hozzászólást!
  • ez sem jó, mert így meg a forrás mapet címzed túl y-nal, hiszen annak még kisebb az y mérete. :)
    egyébként az x-re és az y-ra vonatkozó ciklusaid, és az azokhoz kapcsolódó változók egyformáknak kell lenniük, csak az x/y változik. szóval látható is, hogy katyvasz van.

    mondom, emeld ki a létrehozás/törlés funkciókat első lépésben, utána úgy csináld meg az átméretezést, hogy először meghívod a létrehozást eggyel nagyobb méretre paraméterezve, aztán a régi mapből átmásolod ebbe a dolgokat, és a régi mapre meghívod a törlés függvényt. tudom, hogy szereted a spagettit, de ez a módja.
    Mutasd a teljes hozzászólást!

  • Kár, hogy ezt nem tanítják normálisan az egyetemen.
    Ezt kár C++-nak hívni. C-ben kell megtanulni az alapokat, ha az megvan, akkor C++-t modernül tanítanám.
    Mutasd a teljes hozzászólást!
Címkék
abcd