[c++] Hoe random element pakken uit een C++ map container?

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hallo allemaal,

ik zit met een vraagje.
Ik heb de volgende map gemaakt met 6 elementen:

code:
1
2
3
4
5
6
7
std::map<uint32, bool> guest_map;
guest_map.insert(pair<uint32, bool>(19875, false));
guest_map.insert(pair<uint32, bool>(19874, false));
guest_map.insert(pair<uint32, bool>(19872, false));
guest_map.insert(pair<uint32, bool>(17007, false));
guest_map.insert(pair<uint32, bool>(19876, false));
guest_map.insert(pair<uint32, bool>(19873, false));


Nu moet ik dus uit die 6 elementen, een willekeurig element pakken en daarna komen er nog een paar checks die nakijken of het element te gebruiken is of niet. Zo niet, dan pakt het programma een nieuw willekeurig element.

Maar hoe pak ik een willekeurig element uit mijn container?
Heb de hele middag zitten proberen, maar het enige wat ik kreeg was koppijn :P

Alvast bedankt! _/-\o_

Acties:
  • 0 Henk 'm!

  • Enfer
  • Registratie: Februari 2004
  • Laatst online: 16:32
Kijken hoe groot de map is, en dan aan de hand daarvan een rand loslaten?

Random getal genereren tot en met 6:
code:
1
rand() % 6 + 1;

[ Voor 33% gewijzigd door Enfer op 07-09-2009 20:23 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ja zoiets heb ik geprobeerd, in de vorm van dit:

code:
1
std::map<uint32, bool>::iterator itr = rand()%guest_map.size();


Maar dan krijg ik een initializing error.
error C2440: 'initializing' : cannot convert from 'unsigned int' to 'std::_Tree<_Traits>::iterator'
Ik zal het wel verkeerd bekijken allemaal.

[ Voor 7% gewijzigd door Verwijderd op 07-09-2009 20:25 ]


Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

1) random nummer tussen 0 en map.size() - 1
2) iterator i = map.begin(); for(int j = 0; j < random_nummer; ++i, ++j);
3) i wijst naar je random element

als je graag directe indexering wilt gebruiken, moet je een vector ipv map gebruiken (dan kan je vector[random_index] doen).

daarnaast (weet ik niet zeker) kan je mss ook wel doen:
2) iterator i = map.begin() + random_nummer;

weet niet 100% zeker of map iterators een + operator hebben :(

[ Voor 49% gewijzigd door MLM op 07-09-2009 20:30 ]

-niks-


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hm alles wat ik probeer geeft een initializing error.
Like this:
code:
1
2
std::map<uint32, bool>::iterator randomG = rand()%guest_map.size()-1;
itr = guest_map.begin() + randomG;
error C2440: 'initializing' : cannot convert from 'unsigned int' to 'std::_Tree<_Traits>::iterator'

Acties:
  • 0 Henk 'm!

  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
"Alles" wat je probeert is twee keer hetzelfde...

Je probeert een random nummer toe te wijzen aan een iterator (dat werkt niet, zoals de foutmelding ook aangeeft). MLM geeft bij optie 1 aan hoe het wel moet.

PS: een iterator die een + operator zou ondersteunen :S (het zal allemaal wel kunnen in C++, maar geef mij dan toch maar Java, waar je dat soort flauwekul niet hoeft te verwachten)

[ Voor 15% gewijzigd door Herko_ter_Horst op 07-09-2009 20:54 ]

"Any sufficiently advanced technology is indistinguishable from magic."


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik had hem verkeerd begrepen, my bad :)
Het werkt nu! Thanks allemaal.

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Elke iterator ondersteunt advance(it, n) die delegeert naar ofwel operator+ ofwel een herhaald operator++, of iets slims intern.
Herko_ter_Horst schreef op maandag 07 september 2009 @ 20:50:
PS: een iterator die een + operator zou ondersteunen :S (het zal allemaal wel kunnen in C++, maar geef mij dan toch maar Java, waar je dat soort flauwekul niet hoeft te verwachten)
Handig idd als je een interator niet kan "advancen"; wie gebruikt die flauwekul nou? :)

[ Voor 61% gewijzigd door Zoijar op 07-09-2009 21:11 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Herko_ter_Horst schreef op maandag 07 september 2009 @ 20:50:
PS: een iterator die een + operator zou ondersteunen :S (het zal allemaal wel kunnen in C++, maar geef mij dan toch maar Java, waar je dat soort flauwekul niet hoeft te verwachten)
Ja, idd flauwekul, zo'n perfect logische operatie op een type als een iterator 8)7.
De link die jij mist, waardoor het waarschijnlijk zo onlogisch lijkt, is het feit dat iterators zijn gemodeleerd naar pointers. Het gedraagt zich als een pointer naar een element uit een container. Als je 1 bij een pointer optelt, wijst hij naar het volgende element. Zo ook bij een iterator. Als je * gebruikt krijg je het element zelf, net als een pointer:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int main()
{
    // pointers
    {
        int array[10];
        typedef int* iterator;
    
        iterator begin = array;
        iterator end = array + 10;
        for (iterator i = begin; i < end; ++i)
            std::cout << *i << std::endl;
    }

    // container iterators
    {
        std::vector<int> array(10);
        typedef std::vector<int>::iterator iterator;

        iterator begin = array.begin();
        iterator end = array.end();
        for (iterator i = begin; i < end; ++i)
            std::cout << *i << std::endl;
    }
}

En code wordt alleen maar leesbaarder als alles op een eenduidige manier werkt, ookal is de onderliggende implementatie anders.

Overigens gaat de + operator in het geval van een std::map<>::iterator niet op, omdat het geen random access iterator is. Bij een + verwacht men doorgaans toch een O(1) operatie, maar dat kan nou eenmaal niet voor niet random access iterators. En daarom bestaat de generieke advance() functie, die O(1) is voor random access iterators maar O(N) in alle andere gevallen.

[ Voor 28% gewijzigd door .oisyn op 07-09-2009 23:57 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Refro
  • Registratie: November 2000
  • Laatst online: 21:40
Verwijderd schreef op maandag 07 september 2009 @ 20:44:
Hm alles wat ik probeer geeft een initializing error.
Like this:
code:
1
2
std::map<uint32, bool>::iterator randomG = rand()%guest_map.size()-1;
itr = guest_map.begin() + randomG;



[...]
Als je daar nu gewoon eens van maakt

code:
1
2
int iRandom = rand() % guest_map.size() - 1
std::map<uint32, bool>::iterator randomG =  guest_map.find(iRandom);


Dan zou het gewoon moeten werken let wel op als het element niet in de map zit wijst de iterator naar map.end().

Wat ook zou kunnen is rechtstreeks het random getal gebruiken om in de map te komen

code:
1
2
int iRandom = rand() % guest_map.size() - 1
BOOL bIets = guest_map[iRandom];


Waar je hier wel moet opletten is dat mocht het element niet bestaan het op het moment van accessen wordt aangemaakt.

Als laatste tip door van je map een typedef te maken is het veranderen achteraf simpeler en het declareren van iterators ziet er logischer uit.

code:
1
2
3
typedef std::map<uint32, bool> GuestMap;
GuestMap guest_map; //Declaratie
GuestMap::iterator it; //Aanmaken iterator

Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

daar kan ik het nou niet mee eens zijn.
In jouw gebruik van find() en map[int_waarde] gaan alleen werken als je een map hebt die
1) keytype int heeft en
2) alle keys van 0 tot size() - 1 aanwezig zijn
anders heb je geen "random element uit de map", dan heb je (uitgaande van egale distributie van keys) 99% kans op een hit van default-contructed totdat je meer dan 20 miljoen items in je map hebt...

En als je toch al oplopende keys erin doet, van 0 tot verder, kan je net zo goed een vector gebruiken...

-niks-


Acties:
  • 0 Henk 'm!

  • Refro
  • Registratie: November 2000
  • Laatst online: 21:40
MLM schreef op dinsdag 08 september 2009 @ 08:24:
daar kan ik het nou niet mee eens zijn.
In jouw gebruik van find() en map[int_waarde] gaan alleen werken als je een map hebt die
1) keytype int heeft en
Ok dat is het geval in het voorbeeld dus die aanname durf ik wel te maken.
2) alle keys van 0 tot size() - 1 aanwezig zijn
anders heb je geen "random element uit de map", dan heb je (uitgaande van egale distributie van keys) 99% kans op een hit van default-contructed totdat je meer dan 20 miljoen items in je map hebt...

En als je toch al oplopende keys erin doet, van 0 tot verder, kan je net zo goed een vector gebruiken...
Ok de map[int_waarde] gaat dus inderdaad niet werken en de find() is idd ook niet zo handig omdat je geen idee van de keys hebt. Dus toch maar een iterator op begin (of end) en dan een random aantal maal ophogen (of aflagen).

[ Voor 0% gewijzigd door Refro op 08-09-2009 08:34 . Reden: quote fixed ]


Acties:
  • 0 Henk 'm!

  • Phyxion
  • Registratie: April 2004
  • Niet online

Phyxion

_/-\o_

Verwijderd schreef op maandag 07 september 2009 @ 20:17:
Hallo allemaal,

ik zit met een vraagje.
Ik heb de volgende map gemaakt met 6 elementen:

code:
1
2
3
4
5
6
7
std::map<uint32, bool> guest_map;
guest_map.insert(pair<uint32, bool>(19875, false));
guest_map.insert(pair<uint32, bool>(19874, false));
guest_map.insert(pair<uint32, bool>(19872, false));
guest_map.insert(pair<uint32, bool>(17007, false));
guest_map.insert(pair<uint32, bool>(19876, false));
guest_map.insert(pair<uint32, bool>(19873, false));


Nu moet ik dus uit die 6 elementen, een willekeurig element pakken en daarna komen er nog een paar checks die nakijken of het element te gebruiken is of niet. Zo niet, dan pakt het programma een nieuw willekeurig element.

Maar hoe pak ik een willekeurig element uit mijn container?
Heb de hele middag zitten proberen, maar het enige wat ik kreeg was koppijn :P

Alvast bedankt! _/-\o_
"Nu moet ik dus uit die 6 elementen, een willekeurig element pakken en daarna komen er nog een paar checks die nakijken of het element te gebruiken is of niet. Zo niet, dan pakt het programma een nieuw willekeurig element."

Is het niet makkelijker om gewoon bij de eerste te beginnen en te kijken of het te gebruiken valt, zo nee dan gewoon de volgende?

Hoe dan ook:

int randomValue = rand()%guest_map.size();
dan kan je bij je elementen met guest_map[randomValue];

:)

'You like a gay cowboy and you look like a gay terrorist.' - James May


Acties:
  • 0 Henk 'm!

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Phyxion schreef op dinsdag 08 september 2009 @ 08:44:
int randomValue = rand()%guest_map.size();
dan kan je bij je elementen met guest_map[randomValue];
Nee, dat werkt niet. Sterker nog, gezien het feit dat zijn kleinste element al groter is dan zijn mapsize (17007>6) kun je zelfs bij geen enkel element. Value& map<Key,Value>::operator[](Key) geeft je de Value die bij de destbetreffende Key hoort, en insert desnoods een default-constructed Value als de Key nog niet bestond.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Overigens is een random element pakken uit de map zelf ook nog niet zo handig:
Verwijderd schreef op maandag 07 september 2009 @ 20:17:
Nu moet ik dus uit die 6 elementen, een willekeurig element pakken en daarna komen er nog een paar checks die nakijken of het element te gebruiken is of niet. Zo niet, dan pakt het programma een nieuw willekeurig element.
Als je steeds random uit de map gaat halen, dan zal naarmate het aantal te gebruiken elementen opraakt deze methode er steeds langer en langer over gaan doen, omdat je er niet voor zorgt dat de niet te gebruiken elementen niet meer worden meegenomen in de random trekking. Tenminste, hierbij neem ik aan dat je de getrokken elementen niet wilt verwijderen uit de map. Als dat wel het geval is, dan kun je de rest van deze post negeren.

Denk maar eens aan een zak met 50 rode en 50 groene knikkers. Als je alle rode knikkers uit de zak wilt halen, en je trekt steeds een willekeurig knikker, dan leg je de groene ook niet terug in de zak, omdat je dan als laatst moet zoeken naar 1 rode knikker in een zak 50 overige groene knikkers, waardoor je dus wel erg vaak moet trekken om toevallig die ene rode eruit te halen.

Beter vul je gewoon even een container (een vector bijvoorbeeld) met alle keys (of alleen met alle relevante keys als die check relatief goedkoop is), en dan pak je steeds een willekeurig element uit de vector. Daarna swap je dat random element met het laatste element in de vector, en verklein je de vector met 1. Op die manier pak je steeds een random element uit de relevante elementen, en loop je niet het risico dat je steeds opnieuw een element pakt wat niet relevant is waardoor je weer van voor af aan moet beginnen.

[ Voor 7% gewijzigd door .oisyn op 08-09-2009 11:21 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik heb het al hoor mensen ;)
Verwijderd schreef op maandag 07 september 2009 @ 21:08:
Ik had hem verkeerd begrepen, my bad :)
Het werkt nu! Thanks allemaal.
Als jullie het nog moeten zien:
C++:
1
2
3
4
5
6
7
8
9
10
11
int r_number = rand()%guest_map.size()-1;
                
itr = guest_map.begin();
for (int j = 0; j < r_number; ++itr, ++j);
{
    //  check if the guest isn't spawned already
    if (itr->second == true)
        continue;
}

// goes on to more checks here but irrelevant

[ Voor 42% gewijzigd door Verwijderd op 08-09-2009 14:53 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Als je er dan ook bijzegt wát je dan verkeerd begrepen hebt, is ook leuk voor de andere mensen in de topic :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Naja zoals ik al liet zien. Ik deed het zo:
C++:
1
2
std::map<uint32, bool>::iterator randomG = rand()%guest_map.size()-1;
itr = guest_map.begin() + randomG;


i.p.v wat ik in mijn vorige bericht liet zien.

Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 16-09 22:43
Kweenie maar volgens mij is die modulus nie goed

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op dinsdag 08 september 2009 @ 14:50:
Als jullie het nog moeten zien:
C++:
1
2
3
4
5
6
7
8
9
10
11
int r_number = rand()%guest_map.size()-1;
                
itr = guest_map.begin();
for (int j = 0; j < r_number; ++itr, ++j);
{
    //  check if the guest isn't spawned already
    if (itr->second == true)
        continue;
}

// goes on to more checks here but irrelevant
Vage code. De { .. } lijkt bij de for te horen, maar dat is niet zo want er staat een ; achter de for. Toch doe je een continue in dat blok. Waarschijnlijk staat er nog een lus omheen die je hier niet laat zien, maar ik stel voor om die accolades sowieso weg te halen voor de zekerheid.

Daarnaast klopt je modulo idd niet, zoals farlane terecht opmerkt. En bovendien is mijn vorige post zeer relevant: .oisyn in "\[c++] Hoe random element pakken uit een ..."
Lees nog even het stukje over de knikkers. Waarschijnlijk merk je het niet omdat je map niet groot genoeg is (een rode knikker uit een zak met 1 rode en 3 groene knikkers halen kost niet zoveel trekkingen, gemiddeld 2), maar zodra ie groter wordt heb je kans op erg lange wachttijden (een rode knikker halen uit een zak met 1 rode en 10.000 groene knikkers kost gemiddeld 5.000 trekkingen, terwijl je weet dat er maar 1 rode is)

[ Voor 3% gewijzigd door .oisyn op 08-09-2009 15:32 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Het werkt allemaal anders perfect hoor... Maar toch bedankt, ik zal er naar kijken.
Die { ... } waren inderdaad typefoutjes. Ben gewend dat altijd te doen na een For.

Over dat steeds trager gaan. Het wordt eenmalig uitgevoerd wanneer het object ontstaat. Dit gebeurd in dit geval niet zo vaak.

[ Voor 82% gewijzigd door Verwijderd op 08-09-2009 19:06 ]


Acties:
  • 0 Henk 'm!

  • Andre-85
  • Registratie: April 2003
  • Niet online

Andre-85

Sid

.oisyn schreef op maandag 07 september 2009 @ 23:48:
[...]

Ja, idd flauwekul, zo'n perfect logische operatie op een type als een iterator 8)7.
De link die jij mist, waardoor het waarschijnlijk zo onlogisch lijkt, is het feit dat iterators zijn gemodeleerd naar pointers. Het gedraagt zich als een pointer naar een element uit een container. Als je 1 bij een pointer optelt, wijst hij naar het volgende element. Zo ook bij een iterator. Als je * gebruikt krijg je het element zelf, net als een pointer:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int main()
{
    // pointers
    {
        int array[10];
        typedef int* iterator;
    
        iterator begin = array;
        iterator end = array + 10;
        for (iterator i = begin; i < end; ++i)
            std::cout << *i << std::endl;
    }

    // container iterators
    {
        std::vector<int> array(10);
        typedef std::vector<int>::iterator iterator;

        iterator begin = array.begin();
        iterator end = array.end();
        for (iterator i = begin; i < end; ++i)
            std::cout << *i << std::endl;
    }
}

En code wordt alleen maar leesbaarder als alles op een eenduidige manier werkt, ookal is de onderliggende implementatie anders.

Overigens gaat de + operator in het geval van een std::map<>::iterator niet op, omdat het geen random access iterator is. Bij een + verwacht men doorgaans toch een O(1) operatie, maar dat kan nou eenmaal niet voor niet random access iterators. En daarom bestaat de generieke advance() functie, die O(1) is voor random access iterators maar O(N) in alle andere gevallen.
Je code code is bugy ;)
C++:
1
2
3
4
        iterator begin = array.begin();
        iterator end = array.end();
        for (iterator i = begin; i != end; ++i)
            std::cout << *i << std::endl;

Van een vector is niet gegarandeerd dat het alligned in het geheugen staat. Een iterator > end() kan dus geldig zijn. Je moet testen op i != end.

Lorem
Whenever we feel the need to comment something, we write a method instead. - Martin Fowler
People who think they know everything really annoy those of us who know we don't - Bjarne Stroustrup


Acties:
  • 0 Henk 'm!

  • coubertin119
  • Registratie: Augustus 2002
  • Laatst online: 15-09 17:06
Andre-85 schreef op dinsdag 08 september 2009 @ 19:36:
[...]

Je code code is bugy ;)
C++:
1
2
3
4
        iterator begin = array.begin();
        iterator end = array.end();
        for (iterator i = begin; i != end; ++i)
            std::cout << *i << std::endl;

Van een vector is niet gegarandeerd dat het alligned in het geheugen staat. Een iterator > end() kan dus geldig zijn. Je moet testen op i != end.
Omdat het een RandomAccessIterator is, mag het wel voor zover ik weet. Zie ook http://www.cplusplus.com/...tor/RandomAccessIterator/

Skat! Skat! Skat!


Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

Vectors zijn juist wel na elkaar in het geheugen (net als een native array) dacht ik, dus in dat geval kan je checken op >, maar het is beter om != aan te leren, omdat het werkt op alle containers :)

Daarnaast, "aligned" is een heel ander verhaal (alignment is dat elk element begint in het geheugen op een meervoud van X bytes), dus je gooit nu keywords door elkaar :) Wat jij bedoelt is volgens mij "consecutive" (zonder tussenliggende ruimte en op volgorde)

-niks-


Acties:
  • 0 Henk 'm!

  • coubertin119
  • Registratie: Augustus 2002
  • Laatst online: 15-09 17:06
MLM schreef op dinsdag 08 september 2009 @ 20:07:
Vectors zijn juist wel na elkaar in het geheugen (net als een native array) dacht ik, dus in dat geval kan je checken op >, maar het is beter om != aan te leren, omdat het werkt op alle containers :)
Vectors _hoeven_ dat technisch gezien niet te zijn, iterators zorgen voor de abstractie tussen datalayout en gedrag. Het is voor iterators daarentegen wel heel erg handig dat std::vector intern een array is om die operator te implementeren :).

Skat! Skat! Skat!


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Andre-85 schreef op dinsdag 08 september 2009 @ 19:36:
[...]

Je code code is bugy ;)
C++:
1
2
3
4
        iterator begin = array.begin();
        iterator end = array.end();
        for (iterator i = begin; i != end; ++i)
            std::cout << *i << std::endl;

Van een vector is niet gegarandeerd dat het alligned in het geheugen staat. Een iterator > end() kan dus geldig zijn. Je moet testen op i != end.
Op zich heb je gelijk in de zin dat je bij generieke iterators altijd beter != kunt schrijven, en dat doe ik bij vectors ook altijd. Dit was wat dat betreft een copy/paste foutje. Desalniettemin, je stelling is pertinent onwaar. Elementen in een vector staan per defintie aaneengesloten in het geheugen, en elke random access iterator kun je vergelijken met alle vergelijkingsoperatoren.

Overigens, niet random access iterators ondersteunen mogelijk geen relationele vergelijkingsoperators, waardoor een expressie als iterator > end() compile errors op kan leveren. En gezien je alleen iterators mag vergelijken uit dezelfde containers, kan iterator > end() nooit geldig zijn (anders dan de undefined behaviour gevallen die toevallig true returnen)
coubertin119 schreef op dinsdag 08 september 2009 @ 20:16:
[...]
Vectors _hoeven_ dat technisch gezien niet te zijn
Ik weet niet welke standaard jij erop nahoudt, maar in 23.2.4/1 staat toch echt wat anders:
The elements of a vector are stored contiguously, meaning that if v is a vector<T, Allocator> where T is some type other than bool, then it obeys the identity &v[n] == &v[0] + n for all 0 <= n < v.size().
:)

[ Voor 33% gewijzigd door .oisyn op 08-09-2009 23:12 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
.oisyn schreef op dinsdag 08 september 2009 @ 20:25:
Overigens, niet random access iterators ondersteunen geen relationele vergelijkingsoperators
Dat is weer wat te sterk geformuleerd. Een iterator is pas een Random Iterator als íe aan alle eisen voldoet. Als een iterator wel operator< ondersteunt, maar geen operator+, dan is het geen RandomIterator.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ah ja, is natuurlijk ook zo. Dat iets bepaalde requirements heeft wil nog niet zeggen dat hij louter die requirements moet ondersteunen. Ik zal m'n post iets nuanceren :)

[ Voor 47% gewijzigd door .oisyn op 08-09-2009 23:43 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • coubertin119
  • Registratie: Augustus 2002
  • Laatst online: 15-09 17:06
.oisyn schreef op dinsdag 08 september 2009 @ 20:25:
[...]Ik weet niet welke standaard jij erop nahoudt, maar in 23.2.4/1 staat toch echt wat anders:

[...]

:)
Excuus, die had ik gemist. Assumption is the mother of all fuck-ups :).

Skat! Skat! Skat!


Acties:
  • 0 Henk 'm!

  • ErikKo
  • Registratie: Mei 2009
  • Laatst online: 17-09 18:39

ErikKo

Rippie

.oisyn schreef op dinsdag 08 september 2009 @ 20:25:
Ik weet niet welke standaard jij erop nahoudt, maar in 23.2.4/1 staat toch echt wat anders:

[...]
Je verwijst naar een paragraaf uit een boek of iets dergelijks? Ben benieuwd waarnaar je verwijst, aangezien die quote heerlijk kort maar krachtig is wat ik in nog geen enkel boek ben tegengekomen.

En ik merk weer hoeveel kennis er op dit forum rondsurft: Heb weer wat bijgeleerd van dit topic. _/-\o_

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

ErikKo schreef op dinsdag 08 september 2009 @ 23:27:
[...]

Je verwijst naar een paragraaf uit een boek of iets dergelijks?
Naar de officiele ISO C++ standaard: ISO/IEC 14882:2003. Hij is volgens mij auteursrechtelijk beschermd, maar google maar 'ns ;)

't Is niet echt lekker leesvoer oid (zeg maar vergelijkbaar met een wetboek), maar als je eens echt wilt weten hoe iets zit ipv iemand's eigen interpretatie ervan dan is het wel nuttig :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Andre-85
  • Registratie: April 2003
  • Niet online

Andre-85

Sid

.oisyn schreef op dinsdag 08 september 2009 @ 20:25:
[...]

Op zich heb je gelijk in de zin dat je bij generieke iterators altijd beter != kunt schrijven, en dat doe ik bij vectors ook altijd. Dit was wat dat betreft een copy/paste foutje. Desalniettemin, je stelling is pertinent onwaar. Elementen in een vector staan per defintie aaneengesloten in het geheugen, en elke random access iterator kun je vergelijken met alle vergelijkingsoperatoren.

Overigens, niet random access iterators ondersteunen mogelijk geen relationele vergelijkingsoperators, waardoor een expressie als iterator > end() compile errors op kan leveren. En gezien je alleen iterators mag vergelijken uit dezelfde containers, kan iterator > end() nooit geldig zijn (anders dan de undefined behaviour gevallen die toevallig true returnen)


[...]

Ik weet niet welke standaard jij erop nahoudt, maar in 23.2.4/1 staat toch echt wat anders:

[...]

:)
I stand corrected...

Lorem
Whenever we feel the need to comment something, we write a method instead. - Martin Fowler
People who think they know everything really annoy those of us who know we don't - Bjarne Stroustrup


Acties:
  • 0 Henk 'm!

  • ErikKo
  • Registratie: Mei 2009
  • Laatst online: 17-09 18:39

ErikKo

Rippie

Was zelf ook al aan het googlen gegaan. Was er net achter waar het vandaan kwam.
Overigens gaf deze google een beter resultaat. :)

Was er ook al achter dat het geen leesvoer is, maar wel zeer handige naslagwerk. Thx.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op dinsdag 08 september 2009 @ 17:35:
Het werkt allemaal anders perfect hoor...
Sorry, maar dat is onzin. Jij doet: rand()%guest_map.size()-1

rand() geeft een waarde van 0 t/m RAND_MAX. Jij doet modulo guest_map.size(), dus dat wordt dan 0 t/m guest_map.size()-1. Vervolgens trek je er 1 af, dus dat wordt -1 t/m guest_map.size()-2. Conclusie: het laatste element pak je nooit, en de kans dat je het eerste element pakt is ruwweg 2x zo groot (omdat de for bij zowel -1 als 0 meteen al stopt, waardoor je dus in 2 gevallen de begin iterator overhoudt)

Dat het *lijkt* te werken, betekent niet dat het precies doet wat je wilt.

[ Voor 29% gewijzigd door .oisyn op 09-09-2009 11:27 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hm ik zit toch met een klein probleempje. Het ziet er naar uit dat hij vrijwel willekeurig werkt, maar hij pakt nooit het 5e element. Het 6e element dan wel, maar minder dan de rest heb ik het idee.

Stukje code, hier en daar wat duidelijker gemaakt voor jullie ogen.
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
for (int i = 0; i < 4; ++i)
{
    while (goContinue == false)
    {
        int r_number = NULL;
        r_number = rand()%guest_map.size()-1;
            
        itr = guest_map.begin();
        for (int j = 0; j < r_number; ++itr, ++j);
        
        if (itr->second == true)
            continue;
                
        saveGuestEntry[i] = itr->first;
                
        if (itr->first == definition)
            bool = true;
                    
        if (itr->first == definition)
            bool = true;
                
        goContinue = true;
    }
            
    p_guest[i] = // blabla
            
    itr->second = true;
    
    goContinue = false;
}


Dit wordt eenmalig uitgevoerd wanneer het object ontstaat.
Alvast bedankt.


edit: Nevermind. Je had gelijk Oisyn. Die -1 was onzin. Nu doet hij inderdaad wat ik wil. Hartstikke bedankt ;) Ik duik de theorie nog maar eens een keertje in.

[ Voor 8% gewijzigd door Verwijderd op 09-09-2009 23:09 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Heb je m'n vorige post gelezen? Je trekt nu nog steeds 1 van je random af. Bovendien compilet de code zoals ie daar staat natuurlijk ook niet, met de code op regels 17 en 20 (die bovendien identiek zijn)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • user109731
  • Registratie: Maart 2004
  • Niet online
Verwijderd schreef op woensdag 09 september 2009 @ 23:03:
Het ziet er naar uit dat hij vrijwel willekeurig werkt, maar hij pakt nooit het 5e element.
Het 5e element heeft de hoogste key. Volgens 23.1.2/9 moet een iterator over een associative container idd in non-descending order gaan:
The fundamental property of iterators of associative containers is that they iterate through the containers in the non-descending order of keys where non-descending is defined by the comparison that was used to construct them.
(volgens punt 10 is non-descending == ascending hier, omdat de keys uniek zijn) Dus dat klopt wel ;)
Het 6e element dan wel, maar minder dan de rest heb ik het idee.
Hij zou het 4e element vaker moeten pakken (laagste key, voor -1 en 0, zoals .oisyn al zei).

Leerzaam topic, wel leuk om die standaard eens door te bladeren :)

[ Voor 8% gewijzigd door user109731 op 09-09-2009 23:32 ]


  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
MLM schreef op maandag 07 september 2009 @ 20:26:
1) random nummer tussen 0 en map.size() - 1
2) iterator i = map.begin(); for(int j = 0; j < random_nummer; ++i, ++j);
3) i wijst naar je random element
iterator i = boost::next(map.begin(), random_nummer);

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Verwijderd schreef op woensdag 09 september 2009 @ 23:03:
Stukje code, hier en daar wat duidelijker gemaakt voor jullie ogen.
In plaats van goContinue zou ik break gebruiken.
En int X = NULL? Waarom niet = 0?
bool = true; compileert ook niet...

[ Voor 6% gewijzigd door Olaf van der Spek op 10-09-2009 20:28 ]


  • Soultaker
  • Registratie: September 2000
  • Nu online
Olaf van der Spek schreef op donderdag 10 september 2009 @ 20:11:
iterator i = boost::next(map.begin(), random_nummer);
En hoe verschilt dat van de oplossing met std::advance :?

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Soultaker schreef op donderdag 10 september 2009 @ 21:15:
[...]

En hoe verschilt dat van de oplossing met std::advance :?
std::advance verandert z'n argument en kan dus niet aangeroepen worden met begin().

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
.oisyn schreef op woensdag 09 september 2009 @ 23:12:
Heb je m'n vorige post gelezen? Je trekt nu nog steeds 1 van je random af. Bovendien compilet de code zoals ie daar staat natuurlijk ook niet, met de code op regels 17 en 20 (die bovendien identiek zijn)
Meh, dat waren voorbeelden om het voor jullie wat simpeler te maken.
Ik heb het inderdaad naar een break veranderd later.

Wat is er erg aan NULL trouwens? Ik gebruik het wel vaker. Kan aan de stijl liggen...
Of is dat té offtopic? :P

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

NULL is een C iets, en onder C code is het gedefinieerd als (void*)0, en mag je dus niet eens assignen aan een int. 't Is ook bedoeld voor pointers, niet voor ints. In C++ schrijft men voor pointers doorgaans ook gewoon 0, en voor ints natuurlijk al helemaal.

[ Voor 36% gewijzigd door .oisyn op 16-09-2009 00:33 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • NC83
  • Registratie: Juni 2007
  • Laatst online: 21-08 21:44
Het slechte aan NULL is dat het gerealiseerd is door een #define en niet een keyword. Het is beter om jezelf aan te leren om 0 te schrijven voor een null pointer dit zal namelijk bij iedere C++ compiler werken.

Verder compillet
int x = NULL; op windows en in C++ omdat in windef.h het volgende staat
C++:
1
2
3
4
5
6
7
#ifndef NULL
#ifdef __cplusplus
#define NULL    0
#else
#define NULL    ((void *)0)
#endif
#endif

[ Voor 34% gewijzigd door NC83 op 16-09-2009 01:34 ]

ex-FE Programmer: CMR:DiRT2,DiRT 3, DiRT Showdown, GRID 2, Mad Max

Pagina: 1