c++ problem av typen vector.erase()

Permalänk
Medlem

c++ problem av typen vector.erase()

Hej forumet!

Har ännu ett litet problem med ett program jag håller på att jobba med.
Det är ett skolarbete där man gör en varuautomat (säkert fler som har samma program) med valfritt antal produkter mm.
Man ska kunna köpa, byta ut, lägga till och ta bort produkter.

Nu är jag nästan färdig med allting MEN har stött på problem när man ska ta bort enskilda produkter.

En liten sammanfattning av hur programmet ser ut:

Jag har gjort en klass som heter Automat. Den består av flera funktioner och variabler men huvudfunktionen
är en container av typen list som lägger in nya produkter. Så här ser den ut: list<Automat*> varor;

När man startar programmet så anropas automatiskt den här funktionen:

void Automat::basutbud()
{
// för att det från början skall finnas varor i automaten
// så börjar programmet med ett anrop av denna funktion som ger automaten 6 varor från start.
ant = 0;
varor.push_back(new Automat(++ant, "Kexchocklad", 25)); // listans varor allokerar dynamiskt en ny vara med nr, namn och pris på varorna
varor.push_back(new Automat(++ant, "Brännvin", 15));
varor.push_back(new Automat(++ant, "Fetaost", 27));
varor.push_back(new Automat(++ant, "Gödsel" , 10));
varor.push_back(new Automat(++ant, "Torkarblad", 15));
varor.push_back(new Automat(++ant, "Trisslott", 30));
}

listan varor lägger från start in 6 produkter av typerna int, string och int. alltså nr, namn och pris. so far so good men nu kommer problemet.
När man vill ta bort enskilda varor så går det bara att ta bort string-variabeln från listan.
Så här ser funktionen ut (lite förenklatt):

cout << "Ange numret på varan du vill ta bort....Inväntar val: "; cin >> adminval; // adminval har typen int
for(auto it = varor.begin(); it != varor.end(); it++)
{
if(adminval == (*it)->nr)
{
(*it)->nr.erase(); // funkar inte...nr har typen int
(*it)->namn.erase(); // funkar...namn har typen string
(*it)->pris.erase(); // funkar inte...pris har typen int
}
}

när jag försöker köra programmet får jag felmeddelandet: error C2228: left of '.erase' must have class/struct/union för "nr" resp. "pris".

en annan funktion jag har som tar bort alla varor funkar felfritt. Den ser ut så här:

for(auto it = varor.begin(); it != varor.end(); it++) // loopar igenom varorna
delete *it; // tar bort allt allokerat minnesutrymme
varor.clear(); // listan består nu av pekare med skräpvärden och även dessa skall tas bort.
ant = 0; // nollställ räknaren för antal varor

så här är mitt problem helt enkelt. ledsen för att det blev så mycket text men programmet har hunnit bli lite stort nu
hade vart evigt tacksam för hjälp!!!

en trevlig valborg till alla!!
mvh - johan

Permalänk
Medlem
Skrivet av zolost:

cout << "Ange numret på varan du vill ta bort....Inväntar val: "; cin >> adminval; // adminval har typen int for(auto it = varor.begin(); it != varor.end(); it++) { if(adminval == (*it)->nr) { (*it)->nr.erase(); // funkar inte...nr har typen int (*it)->namn.erase(); // funkar...namn har typen string (*it)->pris.erase(); // funkar inte...pris har typen int } }

när jag försöker köra programmet får jag felmeddelandet: error C2228: left of '.erase' must have class/struct/union för "nr" resp. "pris".

Felet du gör är att du försöker köra en vector funtion på delar av en annan struktur.

Det du borde göra är:

for(iter = vector.begin(); iter != vector.end(); iter++) { if ( *iter = dendusökter ) { vector.erase(iter); delete *iter; } }

Lite pseudocode

Visa signatur

orka

Permalänk
Medlem

Hej tack för svar

jag provade att göra som du sa men jag får ett fel av formen: list iterator not dereferencable

jag skrev såhär:

for(auto it = varor.begin(); it != varor.end(); it++)
{
if(adminval == (*it)->nr)
{
varor.erase(it);
delete *it;
}
}

kunde inte göra samma jämförelse som i ditt exempel, den ville inte kompilera då

Permalänk
Medlem

std::list/std::vector

std::list<std::shared_ptr<Vara> > varor; std::cin >> id; auto it = std::find_if(varor.begin(), varor.end(), [id](std::shared_ptr<Vara> vara) { return (vara->id == id); }); if (it != varor.end()) { varor.erase(it); }

std::map

#include <map> #include <memory> #include <iostream> ... std::map<int, std::shared_ptr<Vara> > varor; varor[0] = std::make_shared<Vara>("Trisslott", 30); varor[1] = std::make_shared<Vara>("Fetaost", 20); int id; std::cin >> id; auto result = varor.find(id); if (result != varor.end()) { varor.erase(result); }

Visa signatur

Intel Core i7-3770K | NVIDIA Geforce GTX 980 | 16 GB DDR3 | DELL P2415Q | DELL U2711 | DELL U2410

Permalänk
Medlem

nej det funkar fortfarande inte

Permalänk
Medlem

OT: Snälla, programmera inte på svenska (om det inte är en skoluppgift som bestämmer)

Permalänk

for( auto it = varor.begin(); it != varor.end(); it++ ) { Automat* ptr = *it; if( ptr->nr == adminval ) { varor.erase( it ); delete ptr; delete *it; break; } }

Skrev i "notepad". Men glöm inte att rensa upp efter dig också ordentligt.
I ditt föregående inlägg skrev du att det inte kompilerade, vad spottade den ur sig för meddelande?

Permalänk
Medlem

Hej! Tack för hjälpen! ska prova detta. kompilatorn skriver: error C2228: left of '.erase' must have class/struct/union
för int variablerna "nr" resp. "pris".

mvh

Permalänk
Medlem

Något att se upp med när du anropar erase på en vector är att alla iteratorer som refererar den vectorn invalideras, eftersom minnet kan allokeras om. Om du fortsätter att iterera med den gamla iteratorn så kommer programmet därför sannolikt krascha. erase returnerar dock en giltig iterator till nästa element i vectorn, så en for-loop som använder erase kan se ut så här:

for(auto it = varor.begin(); it != varor.end(); ++it) { it = varor.erase(it); }

Koden ovan kommer helt enkelt att ta bort alla element i vectorn, dvs. samma som clear.

Ditt problem är dock att du verkar ha missförstått vad din vector innehåller. Den innehåller helt enkelt pekare till objekt av typen Automat, så det är Automat-objekten du vill ta bort och inte de ints och strings som Automat innehåller. Du vill alltså bara anropa delete *it för att ta bort ett objekt, och varor.erase(it) för att ta bort pekaren ur vectorn. Men ta dig en funderare på om du verkligen vill lagra pekare i din vector, det är förmodligen bättre att lagra objekten i den direkt istället. Om du verkligen vill lagra pekare så är det bättre att använda shared_ptr som MagnusL visade.