Verktyg Visningsval
2012-04-30, 16:34   #1

zolost

Medlem

Registrerad: feb 2012

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

Senast redigerad av zolost 2012-04-30 klockan 16:40.
zolost är inte uppkopplad
2012-04-30, 18:20   #2

miffo

Medlem

miffos avatar

Plats: Stockholm

Registrerad: aug 2002

Citat:
Ursprungligen inskrivet av zolost Visa inlägg

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
__________________
orka
miffo är inte uppkopplad
2012-04-30, 19:39   #3

zolost

Medlem

Registrerad: feb 2012

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å
zolost är inte uppkopplad
2012-04-30, 19:59   #4

MagnusL

Medlem

Plats: Linköping

Registrerad: mar 2005

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);
}

Senast redigerad av MagnusL 2012-04-30 klockan 20:32.
__________________
Intel Core i7-3770K | AMD RADEON™ HD 7970 3GB | 16 GB DDR3 | DELL U2711 + DELL U2410
MagnusL är inte uppkopplad
2012-04-30, 22:02   #5

zolost

Medlem

Registrerad: feb 2012

nej det funkar fortfarande inte
zolost är inte uppkopplad
2012-04-30, 22:21   #6

Frexuz

Medlem

Registrerad: jun 2005

OT: Snälla, programmera inte på svenska (om det inte är en skoluppgift som bestämmer)
Frexuz är inte uppkopplad
2012-05-02, 15:55   #7

Kaffemaskinen

Medlem

Kaffemaskinens avatar

Registrerad: maj 2012

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?
Kaffemaskinen är inte uppkopplad
2012-05-03, 14:59   #8

zolost

Medlem

Registrerad: feb 2012

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
zolost är inte uppkopplad
2012-05-03, 16:05   #9

perost

Medlem

perosts avatar

Plats: Linköping

Registrerad: jun 2007

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.
perost är uppkopplad nu
Senaste nyheterna

Redaktionens senaste nyhetsrubriker

Sök jobb