srand in einer klasse benutzen



  • hallo!

    ich habe eine klasse die mir zufallszahlen erzeugt. aber wo rufe ich denn srand auf damit es nicht 2 mal aufgerufen wird?? wenn ich es im konstruktor aufrufe und 2 instanzen der klasse erzeuge wird auch srand 2x aufgerufen. und das darf ja nicht passieren so wie ich das einigen beiträgen aus dem forum entnehme. ich hab über die board-such dann auch noch folgendes gefunden:

    http://www.c-plusplus.net/forum/viewtopic.php?t=59993&postdays=0&postorder=asc&highlight=srand+class&start=10
    (den letzten beitrag von walli mein ich)

    aber auch das funktioniert nicht.
    wie kann ich denn jetzt srand für alle instanzen der klasse nur genau EIN mal aufrufen??? 🙄

    ➡ edit: oh hab mich im forum vertan. wollte eigentlich ins c++ forum. irgendwie verpeilt. sorry!



  • die static var im ctor regelt doch das 😕

    static bool seed = false; 
    if(!seed)
    {
       srand(static_cast<unsigned>(time(0)));
       seed = true;
    }
    


  • ja. das hab ich auch so übernommen. aber es geht nicht. aber ich hab vielleicht vergessen zu sagen das die klasse ein thread ist. hängt das vielleicht damit zusammen??



  • sn0b schrieb:

    aber ich hab vielleicht vergessen zu sagen das die klasse ein thread ist.

    Wie kann eine Klasse ein Thread sein 😕



  • flenders schrieb:

    sn0b schrieb:

    aber ich hab vielleicht vergessen zu sagen das die klasse ein thread ist.

    Wie kann eine Klasse ein Thread sein 😕

    gute frage 😃

    meinst du vielleicht jeder thread erstellt ein objekt? das geht nicht, da ja threads eigene speicherbereiche haben.



  • also ich poste euch jetzt mal meinen code. nicht wundern wenn das proggy sinnlose erscheint, es ist nur vorarbeit für ein anderes projekt.

    #include <string>
    #include <time.h>
    #include <process.h>
    #include <windows.h>
    
    class Zufall {
    
        private:
            std::string zahl;
            int threadid;
            int pos;
    
        public:
            HANDLE h;
            bool laufe;
    
            Zufall(int tid) {
                this->threadid=tid;
                laufe=true;
    
                // Nur einmal seed für alle Instanzen
                static bool randinitalisiert=false;
                if(!randinitalisiert) {
                    srand(time(NULL));
                    randinitalisiert=true;
                }
            }
            virtual ~Zufall() {
                BeendeThread(); // Thread muß beendet sein, BEVOR ...
                CloseHandle(h);
            }
    
            /* Thread starten. */
            void Starte() {
                h=(HANDLE)_beginthreadex(0,0,StarteThread,this,0,0);
            }
            /* Thread beenden. */
            virtual void Beende() {
                laufe=false;
                // Warten das Thread beendet ist:
                if (!WaitForSingleObject(h, 10000)==ERROR_SUCCESS)
                    BeendeThread();
            }
            /* Beende Thread wirklich. */
            virtual void BeendeThread() {
                // Warten das Thread beendet ist:
                WaitForSingleObject(h, 10000);
                if (!TerminateThread(h, 0)) {
                    return;
                }
            }
    
            virtual unsigned Run() {
                printf("*** Zufall %d: Generiere...\n",threadid);
                while (laufe) {
                    while (true) {
                        Sleep(2000);
                        GeneriereZahl();
                        printf("*** Zufall %d: Zahl: %s\n",threadid,zahl.c_str());
    
                        if ( ((pos=zahl.find("100"))>-1) || ((pos=zahl.find("200"))>-1) ) {
                            printf("*** Zufall %d: Eine passende Zahl wurde gefunden!\n",threadid);
                            break;
                        }
                    }
                }
            }
    
        private:
            void GeneriereZahl() {
                zahl="";
                int r;
                char tmp[3];
    //srand(time(NULL));
                r=rand()%300+1;
                itoa(r,tmp,10);
                zahl.append(tmp); zahl.append("-");
                for (int i=0; i<2; i++) {
                    r=rand()%300+1;
                    itoa(r,tmp,10);
                    zahl.append(tmp); zahl.append("-");
                }
                r=rand()%300+1;
                itoa(r,tmp,10);
                zahl.append(tmp);
            }
    
        protected:
            static unsigned CALLBACK StarteThread(PVOID threadParam) {
                Zufall * instance = (Zufall *) threadParam;
                return instance->Run();
            }
    };
    
    int main() {
        Zufall z1(1);
        z1.Starte();
        Zufall z2(2);
        z2.Starte();
    
        while (true) { }
    }
    

    edit: habe den source etwas vereinfacht, damit er leichter zu sichten ist. 🙂

    also problem ist folgendes:
    1. wenn ich srand im konstruktor und nicht in der methode GeneriereZahl() initialisiere liefert er immer(!) die gleichen zufalls zahlen:
    1.Durchlauf:

    *** Zufall 1: Generiere...
    *** Zufall 2: Generiere...
    *** Zufall 1: Zahl: 42-168-35-101
    *** Zufall 2: Zahl: 42-168-35-101
    *** Zufall 1: Zahl: 270-125-79-259
    *** Zufall 2: Zahl: 270-125-79-259
    *** Zufall 1: Zahl: 263-165-6-246
    *** Zufall 2: Zahl: 263-165-6-246

    2.Durchlauf:

    *** Zufall 1: Generiere...
    *** Zufall 2: Generiere...
    *** Zufall 1: Zahl: 42-168-35-101
    *** Zufall 2: Zahl: 42-168-35-101
    *** Zufall 1: Zahl: 270-125-79-259
    *** Zufall 2: Zahl: 270-125-79-259
    *** Zufall 1: Zahl: 263-165-6-246
    *** Zufall 2: Zahl: 263-165-6-246

    X.Durchlauf: s.o.
    ich habe aber hier und auf anderen websites gelesen, das srand nur einmal initalisiert werden darf, damit eben genau dies nicht passiert... 🙄
    2. egal wo ich srand nun initalisiere, die "zufallszahlen" sind bei beiden threads immer gleich...

    was mache ich falsch??? 😕



  • holla!

    anscheinend hat keiner bock den ganzen quelltext durchzukauen... 🙄 muß ja auch keiner. 😃 wäre nur für tips dankbar. z.b. ob das am multithreading liegen könnte.
    ich hab google und die board-suche gequält und dabei außer dem oben erwähnten irgendwie nix sinnvolles gefunden. und das funzt ja nicht so wies soll. bitte helft mir! 🙂



  • Du linkst aber schon gegen die Multithreaded-Version der Standard-lib? (in den Compiler/linker-Einstellungen).

    Es gibt IMHO nur zwei Möglichkeiten: Entweder ist die statische Variable, die rand() benutzt, thread-lokal oder nicht.

    Wenn sie es nicht ist, langt ganz offensichtlich ein srand()-Aufruf am Programmanfang.
    Wenn sie es ist, langt nicht mehr einer (hab das aber nicht getestet). Denn beim Erstellen des Threads müsste der aktuelle srand-Wert vom neuen Thread übernommen werden. Damit hätten beide Threads denselben seed und erzeugen dann auch exakt die gleichen "Zufallszahlen". Du müsstest dann also am Beginn jeder Thread-Funktion srand aufrufen, allerdings nicht mit time() als Paramter. Wenn du zwei Threads innerhalb einer Sekunde erstellst, würden sie sonst denselben seed-Wert bekommen.
    Du könntest für srand z.B. eine Zahl nehmen, die du vorher mit rand() erzeugt hast.

    Ob srand für jeden Thread aufgerufen werden muss oder nicht müsste eigentlich in der Dokumentation deines Compilers stehen (das ist nämlich AFAIK nicht vom Standard abgedeckt).



  • ui! 😮 das hört sich aber kompliziert an... naja ich such jetzt erstmal die doku zu meinem dev-c++...
    erstmal vielen dank, auch wenn ich das gefühl hab das ich mich nochmal dazu melden werde 😉


Anmelden zum Antworten