Zufalls Funktion
-
Wenn du die Variable als 'static' deklarierst, wird sie nicht auf dem Stack untergebracht und überlebt schon von sich aus das Ende der Funktion. Da ist es nicht nötig, sich noch zusätzlichen Heap-Speicher anzufordern (der übrigens nie wieder freigegeben wird).
PS: Und den Flüchtigkeitsfehler hast du vermutlich an der falschen Stelle ausgemerzt - lass lieber das "i<*hv+1" in der for-Schleife weg.
-
So das wäre jetzt dei vollendete rnd Funktion. Ist doch in Ordnung oder? Einen Zeiger auf den Heap musste ich leider drin lassen.
//c ist in welchem Abstand eine Zahl wieder kommen darf! //Also wenn eine Zufallszahl gekommen ist darf sie erst nach c anderen //Zufallszahlen wieder kommen. long rnd(long a,long b,int c) { int Zufall=(rand() % (b-a+1)) + a; static int *temp=new int[c]; static int counter=0; static int hv=0; if (counter>c) { counter=0; } if (hv>c) { hv=c; } for(int i=0;i<hv+1;i++) { if(Zufall==temp[i]) { return rnd(a,b,c); } } temp[counter]=Zufall; counter++; hv++; return Zufall; }So is ja alles schön und gut jetzt, aber mir ist aufgefallen das ich die Funktion ja nur einmal einsetzen kann (Wie gesagt ich benutz die ja um bei meinem Bot durch Zufall vector strings auszulesen). Mh weil wenn ich sie dann nochmal starte dann sind ja immer noch die alten Werte drin. Versteht jemand was ich mein? Das is ja natürlich beabsichtig das er sich die Werte merkt, ja aber wenn ich dann z.B. für meinen Bot aus einem anderen vector string lese dann stehen in temp ja noch die alten Werte und so drin. Und *temp kann man nicht überschreiben da es ja static ist und wenn es nicht static wäre würde es sich aber nichts mehr merken und würde dauernd überschrieben werden --> SPEICHERLECKS! Mh äh is jetzt irgendwie so eine Zwickmühle! Kann ich die Funktion jetzt echt nur einmal auf einen vector ansetzen oder lässt sich da noch was dran drehen?
Dankeschön schon mal im Voraus.
-
Du könntest deinen Zufallsgenerator als Objekt anlegen:
class Random { long min,max,count; std::deque<long> values; public: Random(long a,long b,long c) : min(a),max(b),count(c) {} long getZahl() { long Zufall; do Zufall=rand()%(max-min+1)+min; while(find(values.begin(),values.end(),Zufall)!=values.begin()); values.push_back(Zufall); if(values.size()>count) values.push_front(); return Zufall; } };
-
Ehm, vielleicht hat mich Java berufsmäßig schon verdorben, aber muß das nicht heißen:
*(temp[counter])=Zufall;Weil sonst setzt du ja die Speicheradresse zufällig, und nicht den int-Wert.
Und wenn du mehrere Vectoren durchlaufen willst, müsstest du nur den Counter wieder auf Null zurück setzen. Aber irgendwie ist dein Design wirklich etwas crazy.
Ich würde das ganze irgendwie anders lösen. Ich würde der rnd-Funktion gleich nen vector übergeben und gleich umsortieren.
-
Stromberg schrieb:
So das wäre jetzt dei vollendete rnd Funktion. Ist doch in Ordnung oder? Einen Zeiger auf den Heap musste ich leider drin lassen.
//c ist in welchem Abstand eine Zahl wieder kommen darf! //Also wenn eine Zufallszahl gekommen ist darf sie erst nach c anderen //Zufallszahlen wieder kommen. long rnd(long a,long b,int c) { int Zufall=(rand() % (b-a+1)) + a; static int *temp=new int[c]; static int counter=0; static int hv=0; if (counter>c) { counter=0; } if (hv>c) { hv=c; } for(int i=0;i<hv+1;i++) { if(Zufall==temp[i]) { return rnd(a,b,c); } } temp[counter]=Zufall; counter++; hv++; return Zufall; }Nein, das new muss nicht drin bleiben, static ist static, da musst du nicht new bemühen.
Weiss nicht was daran so schwer zu verstehen ist.
-
Ja doch new muss schon sein, weil das array temp ist doch noch ungewisse, man weiß doch nicht wie groß es wird deshalb kommt es auf den Heap?
Meinst du etwa so?static int temp[c];Da kommt bei mir n Error:
Compiling: C:\MinGW\Andi\C++\rnd funktion.cpp
C:\MinGW\Andi\C++\rnd funktion.cpp: In functionlong int rnd(long int, long int, int)': C:\\MinGW\\Andi\\C++\\rnd funktion.cpp:23: error: storage size oftemp' isn't constant
C:\MinGW\Andi\C++\rnd funktion.cpp:23: error: size of variable 'temp' is too large
Process terminated with status 1 (0 minutes, 0 seconds)
2 errors, 0 warnings
-
Mit new ist schon korrekt, wenn die Größe erst zur Laufzeit bekannt ist. Nur vergisst du immer am Ende deine mit new reservierten ints mit delete zu zerstören!!!
Speicherleck!!!Und dann brauchst du es auch nicht static machen, wenn du es eh bei jedem Durchlauf neu anlegen mußt.
-
@CStoll
1. Was ist den:std::deque<long> values;Is das sowas wie:
std::vector<long> values;????
2. Was bedeutet der Befehl "find" in der while schleife, äh den kenn ich nämlich auch nicht. Kanbnst mir das auch erklären.
3. "push_front();" <-- den Befehl kenn ich auch nicht. Ist doch son vector Befehl oder? Schaut so aus finde ich. Obwohl ich das coole Tutorial von Artchi durchgemacht habe aber, aber an push_front(); kann ich mich nicht erinnern. Kannst mir auch das erklären. Sonst hab ich alles soweit verstanden.@Artchi
"*(temp[counter])=Zufall;" <-- das verstehe ich nicht, ich hätte da aber dann "*temp[counter]=Zufall;" geschrieben warum müssen den da solche "( )" hin?Dankeschön schon mal im Voraus.
-
@Artchi
Ja wenn es jetzt aber doch heißt:static int *temp=new int[c];dann wird es doch wegen static nicht neu deklariert oder? --> keine Speicherlecks
Und ich kann doch nicht "delete []temp;" machen, weil der sich das ja dauerhaft merken soll. Wenn ich es lösche dann is es ja weg und die letzten c Zufallszahlen weiß er ja dann nicht mehr. Mh ich sags ja Zwickmühle. Aber man muss das doch auch nicht deleten weil es läuft halt einfach bis zum Programm ende durch und wird gant zum Schluss deleted. Oder? Wer erfreut über deinen fachlichen Rat. Dankeschön schon mal im Voraus.
-
Stromberg! Ich will dir ja nicht zu nache treten, aber vieles was du fragst, kannst du auch selber nachlesen. Wir müssen hier doch nicht jede einzelne Funktion jeder Klasse der Standardlib erklären? Ich habe dir mind. 3 mal hier im Forum http://www.cppreference.com genannt!!! Schlag da endlich nach!!!!!!!
push_back, push_front usw. sind dort alle erklärt! Teilweise braucht man push, back und front nur ins deutsche überseten und schon weiß man was sie machen, ohne das man das nachschlagen muß. push_back heißt nach hinten legen, push_front nach vorne legen. Und, so schwer???
Auch std::deque (Double-ended Queues) ist in der cppreference.com erklärt.
Und besorg dir mal ein vernünftiges C++ Buch, oder schau hier in das Magazin-Forum (weiter unten!) da sind Artikel zur C++ Standardbibliothek, wo alles erklärt wird.
-
Stromberg schrieb:
@Artchi
Ja wenn es jetzt aber doch heißt:static int *temp=new int[c];dann wird es doch wegen static nicht neu deklariert oder? --> keine Speicherlecks
Und ich kann doch nicht "delete []temp;" machen, weil der sich das ja dauerhaft merken soll. Wenn ich es lösche dann is es ja weg und die letzten c Zufallszahlen weiß er ja dann nicht mehr. Mh ich sags ja Zwickmühle. Aber man muss das doch auch nicht deleten weil es läuft halt einfach bis zum Programm ende durch und wird gant zum Schluss deleted. Oder? Wer erfreut über deinen fachlichen Rat. Dankeschön schon mal im Voraus.Sorry, habe mich da selber vertan. Wird nur einmal aufgerufen das new.
-
Schau mal hier rein:
http://www.c-plusplus.net/forum/viewtopic-var-t-is-143816.htmlViele Artikel zu C++ findest du auch hier:
http://www.c-plusplus.net/forum/viewforum-var-f-is-55.html
-
Mit new ist schon korrekt, wenn die Größe erst zur Laufzeit bekannt ist.
Und wenn Du schon am nachlesen bist, schau Dir mal std::vector an. Da könntest Du dann ohne leak auskommen (das static hilft hier nicht gegen den leak) und das new sparen

-
Artchi schrieb:
Mit new ist schon korrekt, wenn die Größe erst zur Laufzeit bekannt ist. Nur vergisst du immer am Ende deine mit new reservierten ints mit delete zu zerstören!!!
Speicherleck!!!Und dann brauchst du es auch nicht static machen, wenn du es eh bei jedem Durchlauf neu anlegen mußt.
Ja, aber sorry, das in dem Beispiel ist trotzdem Blödsinn, denn eine static Variable wird bloss 1x initialisiert, nämlich beim ersten Funktionsaufruf.
Was ist denn wenn ich die Funktion zuerst mit 1, 100, 10 aufrufe, und dann mit 1, 100, 100? Ba-da-boom.
Überhaupt ist es ziemlich witzlos den Speicher fürs "Backlog" dynamisch anzulegen -- es sei denn es gibt eine "init" Funktion der ich die grösse dieses Backlogs mitgeben kann.
Auch wenn man die Funktion "korrigiert", wenn ich z.B. 100 für c übergeben heisst das nicht dass die Funktion garantieren kann dass das Backlog auch effektiv 100 Einträge lang ist - was wenn es mit 10 angelegt wurde, dann 99 weitere Aufrufe mit 10 kommen, und dann kommt ich mit meinen 100 daher. Dann kann ich das Backlog zwar dynamisch grösser machen, aber die Werte der letzten 100 Aufrufe hab ich trotzdem nicht, ich hab bloss 10. Das ist doch alles Blödsinn (sorry, aber ich seh das so).Wie schon mehrfach gesagt wurde gehört das auch nicht in die "rnd" Funktion. Und was "state" hat sollte IMHO einfach ein Objekt sein, also sollte eine Klasse her. Dann kann ich auch ganz einfach Methoden definieren um die Grösse des Backlogs zu setzen oder abzufragen. Dann gibts auch das "static" Problem nichtmehr. Dann wird alles gut

So wie es jetzt ist ist es eine sehr verhunzte Version des Singleton Patterns.
-
Ja, deque ist sowas ähnliches wie'n vector, nur daß er auch am Anfang der Sequenz Daten anfügen/löschen kann (das geht per push_front() bzw. pop_front()). Und find() ist ein STL-Algorithmus, der (wie der Name schon sagt) einen Wert in einem Bereich findet.
Für ausführlichere Erklärungen empfehle ich dir mal einen Blick in meine Serie "Aufbau der STL" im Magazin
