C++ vector

Fórumok

Arduino-ban mi a különbség?

 

1) std::vector<String> cmd(1);

2) String data[500];

 

Első esetben dinamikusan nő a tömb cmd.push_back(""); utasítással a program elején, később nem változik.

A második esetben lehet az első változó a data[328] lesz, ehhez jobb a vector data.resize(329); , vagy inkább a String data[500]; a helyes megoldás?

Ezt a vektor izét nem ismerem, nem találtam hozzá számomra érthető leírást.

Ne ChatGPT-t, nem jött be.

Köszönöm a rám fordított időt a válaszolónak.

Hozzászólások

A vector egy C++-os STL-es adatszerkezet, ami dinamikusan foglal, menet kozben valtoztathato a merete. Olyan, mint a Java-s ArrayList, vagy a Pythonos List. Nem lancolt lista, egy tombhoz hasonloan O(1)-ben lehet egy adott indexu elemehez hozzanyulni - a beszuras, meg a belsejebol torles persze lassu lesz.

A masik egy sima statikus meretu tomb, annak minden elonyevel es nyugjevel.

Arduinon  - meg mikrokontrollereken ugy altalaban - tipikusan nem szeretik a menet kozben valtozo meretu dolgokat, a dinamikus memoriakezelest, meg effeleket. De alapvetoen attol fugg, mit szeretnel.

Ha lehet olyan, hogy eloszor a 328-as indexet irnad, akkor nem biztos, hogy a vectort keresed. A Map, HashMap meg hasonlok lehet, hogy jobban megfelelnek - persze attol fugg, mit szeretnel (nem biztos, hogy ez az STL-es nevuk, mar par eve nem nyultam C++-hoz).

A strange game. The only winning move is not to play. How about a nice game of chess?

Szerkesztve: 2025. 07. 27., v – 22:36

Ha elore nem (nagyon) ismert elemszamu/hosszusagu tombot (vagy barmifele objektumot, adatszerkezetet) csinalnal, akkor az elejen vedd sorban hogy mit szeretnel vele csinalni es ezen lepesek kozul melyeket szeretned gyorsan (azaz elemszamtol lenyegeben fuggetlenul) megvalositani: (ki)kereses, beszuras (elejere, vegere, barhova), torles. Mindket megoldas amit irtal jo  (helyes) lehet, kerdes hogy mit szeretnel valojaban.

Illetve nalad meg az is egy erdekes kihivas hogy ezen nem (nagyon) ismert elemszamu/hosszusagu tomb egyes elemei is valtakozo meretuek/hosszusaguak. Merthogy stringek. Meg akkor is mas fajta megoldas lehet az optimalis hogyha a magasabbszintu objektum valtakozo meretu de az elemei (stringek) elore ismertek, adott meretuek: peldaul random, fix meretu token-ek esnek be kivulrol de nem tudni mennyi (pl card image jellegu adatokbol valamennyi). Meg akkoris ha forditva, a magasabb szintu objektum fix meretu de az egyes elemei valtakozo hosszuak (pl a juzer megadhat 10 parancsot, de a parancs lehet par byte-tol kezdve par kilobyte-osig kb minden). 

Az std::vector-nak van merete, es kapacitasa. Garantalt, hogy osszefuggo memoriaterulet van lefoglalva az elemeknek. A kapacitas mondja meg, hogy hanynak, a meret meg azt, hogy hany elem van benne eppen. Ha a konstruktornak megadsz egy szamot, akkor az lesz a merete, es az osszes elem inicializalva lesz. Megkockaztatom, hogy a kapacitas is ez lesz, es nem nagyobb. Szoval a fenti peldaban cmd[0]-ra rogton hivatkozhatsz, egy kovetkezo push_back()-tol a vector-nak ket eleme lesz, a kapacitasa meg, ha valoban 1 volt, akkor noni fog, vagyis uj memoriaterulet lesz foglalva, aztan masolas (adattagonkent) aztan a regi felszabaditva.

Szoval, ha std::vector-t akarsz hasznalni, nem tudod, elore, hogy hany elemed lesz, csak azt, hogy maximum hany, es el akarod kerulni az ujrafoglalasokat, meg masolasokat, legjobb, ha *nem* adsz meg meretet a konstruktorban, hanem rogton utana egy reserve() hivassal beallitod a kapacitast.

std::vector<String> cmd;
cmd.reserve(500);

Ez egyetlen memoriafoglalassal jar. (Ez a konstruktor nem foglal.) Ettol meg egy elem sem lesz, benne, de push_back()-kel rakhatsz bele max 500-at, vagy atmeretezheted (pl. resize(400)) ujrafoglalas es masolas nelkul.

"String" tipus nincs az STL-ben, felteszem `std::string`-re gondoltal.

Mi az, amit igazából szeretnél? Ez a "328" nagyon-nagyon arra utal, hogy nem olyasmit, amire akár a String, akár a vector való.

Egy ötszáz elemes szring tömb, amiről lövésem sincs hogy mire lesz használva. Az se biztos hogy 500, ez a rendszer indításakor dől el (setuban az user beállítja). A ramon cigánykodok, hogy ne menjen a stabilitás kárára. Tudom, valamit valamiért.

Kicsit hülyén írtam le a kérdést.

Van egy tömböm amit std::vector<String> cmd(1) hozott létre.

Ez minden új hozzáadott sorral nő. cmd.push_back("");

Ha szükéges, akkor a már létrehozott indexen tárolt sztring módosítható.

 

Van egy másik tömböm, amit String data[x] hozott létre.

x a flashból van kiolvasva.

Ez adatokat tárol. Lehet az első parancs ami a tömbbe ír a 328. indexre akar berakni valamit. Az adatok módosíthatóak.

Arra gondoltam hogy egy maxIndex változó tárolja az utoljára használt indexet, ha legközelebb használom a tömböt, ha az az index nagyobb mint maxIndex, akkor átméretezem a tömböt akkorára.

 

Ezek globális tömbök.

Az a kérdés hogy

1) std::vector<String> data(1);

2) String data[x];

közül melyiket célszerűbb használni hogy a lehető legkisebb mértékben töredezzen a ram és sok szabad maradjon.

Esetleg valami alternatív megoldás amiről nem tudok.

Ha ki szeretnél hagyni indexeket: a vektor hasonlít a tömbhöz, mindkettő 0-ás indextől kezd, és folyamatos, azaz elpazarolja az üres helyeket.

A vektor viszont ahogy részben már írták:

  • nyilvántartja a méretét, azt nem neked kell;
  • a kapacitását is, és az is változhat (a tömböd kapacitása 500 és nem változtatható).
  • Az adat nem a stack-en, hanem a heap-en foglal helyet, bár a metaadat stack-en van (kapacitás, méret, adat címe).

Ha helyhatékonyan szeretnél indexelt gyűjteményt, a map vagy unordered_map lenne jó (ha a kulcsod a sorszám, akkor értelemszerűen a map, mert az rendezett).  Viszont Arduinora nincs meg a teljes STL.

Legegyszerűbb talán:

struct Sor {
    int sorszam;
    std::string tartalom;
}
std::vector<Sor> program;

Ez persze gyors nem lesz, de memóriával spórolós.  Keresni így lehet:

if (program[i].sorszam == ...) {
    dolgozas(program[i].tartalom);
}

Vagy a vektor helyett lehet láncolt lista:

std::list<Sor> program;

ha szerkeszteni is kell az adatot menet közben, akkor ez esetben talán jobb, de ha fixen beadják az egészet, onnantól csak olvasható, akkor a vektorra szavazok.

Vagy ha van jól működő STL (vagy hasonló, amiben van map) Arduinora, az lenne a legjobb.

+1 a láncolt listára, a memóriával ez fog a leghatékonyabban bánni. Ha esetleg nincs map arduinora, láncolt listát akkor sem bonyolult létrehozni. A fönti Sor structot kell kiegészíteni egy pointerrel. A beszúrás (bárhová) és a törlés is gyors, egy O(n) keresés után O(1). Üres sor pedig nem foglal helyet. Ja, és nem kell előre konfigurálni, hogy hány sor lesz.

Debian - The "What?!" starts not!
http://nyizsa.blogspot.com