Zufallszahl | switch case | Variable | Fehler



  • Michi8080 schrieb:

    ja das ist ja das komisch dabei .... eigentlich sind da nur 2 Klammern ..
    die erste schließt die switch-Anweisung und die zweite die schließt die IF-Anweisung des "PDT"-schedulers....

    Ja, und schau mal, wo das else steht...

    Aber wenn du einheitlich einrücken würdest (dazu gehört öffnende und schliessende Klammern auf gleicher Höhe), wäre das auch gleich viel klarer. Ausserdem könntest du den Code in mehrere kleine Funktionen aufteilen, dann hast du ein viel bessere Übersicht.



  • Ich weiss jetzt, wo der Fehler ist, aber du sollst deinen Code einrücken lernen und am besten auch gleich auslagern. So kommst du nicht weit.

    Du hast ein } am falschen Ort.. Wenn du den Code eingerückt hättest, dann hättest du das gemerkt..



  • Danke! .. ja das stimmt .... in Funktionen aufteilen ist eine gute IDEE, bin noch Anfänger...

    ich habe jetzt es mit mehr oder weniger Klammern versucht und leide ohne Erfolg 😞 ...
    aber dann sobald ich den den letzten else-Zweig :

    else
       delete upper_msg;
    delete msg;
    

    entfernt habe.... lief die Compilierung weiter 😉

    aber jetzt ein ganz komischer Fehler ?? 😞

    sagt euch

    In function `CommonPartSublayerScheduling::handleMessage(cMessage*)':
    (.text+0x14a2): undefined reference to `CommonPartSublayerScheduling::zufall(int)'
    (.text+0x14ed): undefined reference to `CommonPartSublayerScheduling::zufall(int)'
    (.text+0x1538): undefined reference to `CommonPartSublayerScheduling::zufall(int)'
    (.text+0x1583): undefined reference to `CommonPartSublayerScheduling::zufall(int)'
    (.text+0x15ce): undefined reference to `CommonPartSublayerScheduling::zufall(int)'
    collect2: ld gab 1 als Ende-Status zurück
    

    etwas?????



  • Warum sollte man als Anfänger keine Funktionen benutzen können?! - Du benutzt ja auch schon eine, also wo ist das Problem?!

    Was auch hilft ist den unwichtigen Code mal rauszunehmen. Dann hast du auch einen besseren Überblick..



  • Du scheinst die Funktion CommonPartSublayerScheduling::zufall(int) nicht definiert zu haben. Zumindest nicht an einem Ort, wo sie der Linker findet.

    Und den else -"Zweig" (nur das erste delete gehörte dazu) solltest du nicht entfernen, wenn du damit den Speicher nicht mehr freigibst. Besser die Klammer verschieben.



  • - nein natürlich kann ich auch Funktionen verwenden und werde es mir vornehmen, noch mehr zutun als bis jetzt!

    - zu dem Fehler :
    Kann es sein das ein Linker-Fehler deswegen auftrifft weil man die Funktion nicht bei der ::initialize Funktion gesondert definiert hat?
    Ich habe ja die zufall() im Header mit

    int zufall(int WERT);
    

    deklariert und wie man an dem Code sehen kann , dann in der .cc auch Definiert.

    reicht es vielleicht nicht aus???

    die Methode zufall() ist im Header als private , es sollte glaube ich kein Problem sein, oder?



  • Was ist zufall nun? Eine freie Funktion oder Memberfunktion?

    Die Linkermeldung spricht für Memberfunktion, dass sie private ist auch, aber die Deklaration ist ja global? 😕



  • also, ich erweitere Code das schon fertig ist. Und es sind um die 50.h und .cc drin enthalten.

    Ich bin noch Anfänger.

    Ich wollte den vorhanden Code einfach um einen "scheduler" erweitern, der eine neue Methode zufall() benutzt.

    Ich weis das Memberfunktion die Funktionen von z.B. Strukturen sind. Ich habe Klassen, was kein Unterschied macht oder?

    Ich dachte das wenn ich in Header die Funktion als Prototyp deklariere, dann reicht es aus, um in der .cc auf diese Deklaration zuzugreifen und die Definition zuschreiben. Sobald das steht, DACHTE ich mir dass ich dann innerhalb dieser .cc auf diese Funktion problemlos zugreifen kann.

    ich sehe bestimmt etwas verkehrt? 😕



  • Michi8080 schrieb:

    Ich dachte das wenn ich in Header die Funktion als Prototyp deklariere, dann reicht es aus, um in der .cc auf diese Deklaration zuzugreifen und die Definition zuschreiben. Sobald das steht, DACHTE ich mir dass ich dann innerhalb dieser .cc auf diese Funktion problemlos zugreifen kann.

    Das stimmt eigentlich schon.

    Doch wie gesagt sehe ich das Problem wo anders: Die Definition scheint nicht mit der Deklaration übereinzustimmen. Genauer gesagt vermischst du Memberfunktionen und freie Funktionen.

    Wenn du die Klasse im Header hast, also so...

    class CommonPartSublayerScheduling
    {
        public:
            int zufall(int WERT);
    };
    

    ...dann ist die Memberfunktion zufall() bereits deklariert. Dann kannst du die Definition in die .cc- oder .cpp-Datei schreiben, und sofern du diesen Header einbindest, sollte alles gut sein.

    Wenn du die Methode dann einsetzt, musst du ein zugehöriges Objekt haben. Oder du machst sie gleich statisch, sodass sie sich ähnlich wie eine freie Funktion verhält, aber dem Scope und Zugriff der Klasse unterworfen ist.



  • GESCHAFFT 😉

    also erstmal die Frage : wenn ich die Funktion in Header als static deklariert hätte, dann hätte es also geklappt?

    so habe ich die zugehörige Klasse hinzugefügt, bzw. den Scope davor gesetzt (bestimmt falsche Ausdrucksweise)
    int CommonPartSublayerScheduling::zufall(int a) {
    ....

    gibt es eigentlich Vorteile wenn ich static benutzt hätte?



  • Michi8080 schrieb:

    wenn ich die Funktion in Header als static deklariert hätte, dann hätte es also geklappt? [...] gibt es eigentlich Vorteile wenn ich static benutzt hätte?

    Das kann ich so nicht sagen, weil ich dein Problem immer noch nicht genau kenne.

    Beispielsweise sehe ich immer noch nicht ein, warum zufall() jetzt eine Memberfunktion ist. Greift sie auf private Membervariablen der Klasse zu? Gehört sie zu einem Objekt und reagiert je nach Objekt anders?

    Ansonsten kannst du eine statische Klassenfunktion machen, wenn du findest, die Funktion gehöre logisch zur Klasse (zum Beispiel weil sie auf statische Member zugreift), sei aber unabhängig von deren Instanzen. Wenn sie nichts direkt mit der Klasse zu tun, machst du am besten eine freie, globale Funktion.



  • alles klar!

    Also ich bin wie gesagt, kein Experte 🙂 ...
    aber ich sehe den Code ... & im Code waren in dieser .cc alle Funktionen, Methoden der Klasse und wurden mit Scope-Operator benutzt.
    Logisch gehört für mich zufall() natürlich nicht zu der Klasse, da ich ja nur Zufallszahlen erzeugen will und diese dann für meine case´s nutzen will.

    Aber naja...es läuft & ich bin HAPPY 🙂

    nun zu dem Thema mit srand()...das mann es nur 1 mal aufrufen sollte und nicht jedesmal wenn ein von fünf case´s genommen wird.

    D.h. ich muss diese Zeile

    srand( (unsigned) time(NULL) ) ;
    

    aus der Methode zufall() herausnehmen?
    Und Global z.b. direkt in

    void CommonPartSublayerScheduling::initialize() {
    ......
    ......
      srand( (unsigned) time(NULL) );
    .....
    .....
    

    reinnehmen?
    Ich habe noch nie mit srand() gearbeitet. Ich weis nur dass wenn man Zufallszahlen erzeugen will, dann kommen immer wieder die gleichen raus. Und srand mit Time , erzeugt die Zufallszahlen in Abhängigkeit von der aktuellen Zeit. Also besser randomisiert. Allerdings hört hier schon mein WISSEN über srand() auf 🙂



  • srand machst du am besten bereits in der main rein. Funktionen können ja mehrmals aufgerufen werden und eigenen sich daher nicht.

    srand initialisiert den Zufallsgenerator mit einem seed, den du übergeben musst, damit auch "zufällige" Zahlen rauskommen. Wenn man z.B einen festen Wert eingibt, kann man seine "zufällige" Applikation testen und immer mit den gleichen Werten rechenen. (also der gleichen Abfolge). Für Debuggen Gold Wert.



  • Michi8080 schrieb:

    Logisch gehört für mich zufall() natürlich nicht zu der Klasse, da ich ja nur Zufallszahlen erzeugen will und diese dann für meine case´s nutzen will.

    Aber naja...es läuft & ich bin HAPPY 🙂

    Hm. Wenn es jetzt eine Memberfunktion ist, solltest du es unbedingt global machen. Sonst kommt irgendwann der Zeitpunkt, wo du nicht mehr HAPPY bist. 😉

    Michi8080 schrieb:

    Ich habe noch nie mit srand() gearbeitet. Ich weis nur dass wenn man Zufallszahlen erzeugen will, dann kommen immer wieder die gleichen raus. Und srand mit Time , erzeugt die Zufallszahlen in Abhängigkeit von der aktuellen Zeit. Also besser randomisiert. Allerdings hört hier schon mein WISSEN über srand() auf 🙂

    Also, etwas weiter ausgeholt. In der C++-Standardbibliothek (genauer gesagt dem C-Teil) gibt eine Funktion, um Zufallszahlen erzeugen. Die erzeugten Zahlen sind jedoch nicht wirklich zufällig, sondern werden deterministisch durch Algorithmen erzeugt. Mit der Funktion rand() forderst du eine solche Pseudozufallszahl an.

    Weil der Zufallsgenerator eben deterministisch verläuft, liefert er bei jedem Programmstart die gleichen Zahlen. Um wenigstens da ein bisschen Zufälligkeit reinzubringen, gibt es srand() - eine Funktion, die den Startwert setzt, von dem die nachfolgenden Zufallszahlen abhängen.

    Nun zum Grund, warum man srand() nur einmal aufrufen sollte: Der erwähnte Algorithmus basiert auf dem Konzept des linearen Kongruenzgenerators (halt einfach eine Art von Zufallsgeneratoren). Dessen erzeugte Zahlenfolgen erfüllen gewisse Kriterien, die als "Zufälligkeit" interpretiert werden können (darunter Gleichverteilung, nicht zu starke Korrelation aufeinanderfolgender Werte). Diese Forderungen können nur unter der Bedingung erfüllt werden, dass der Algorithmus wie geplant abläuft. Das tut er, solange man immer brav rand() aufruft. Er benutzt dann nämlich die neu erzeugten Zahlen wiederum als Startwert und arbeitet so rekursiv. Mit srand() stört man diesen Ablauf, indem man den momentanen Wert neu setzt. Damit kann die erwartete Zufälligkeit nicht mehr gewährleistet werden.



  • ok! jetzt verstehe ich den GRUND!

    jetzt muss ich nur wissen WIE ich es mache und wohin ich den srand() setze?

    in die Initialisierung wie oben schon angegeben? oder woanders?

    ich meine wenn srand() nur 1mal aufgerufen werden soll, dann soll er NICHT innerhalb der Methode zufall() stehen, richtig?



  • Michi8080 schrieb:

    in die Initialisierung wie oben schon angegeben? oder woanders?

    Hauptsache, es wird nur einmal aufgerufen. Wird es das bei der Init() -Methode? Vielleicht besser, du schreibst es an den Anfang von main() - ich hoffe schwer, dass es da nicht mehrmals aufgerufen wird. 😉

    Michi8080 schrieb:

    ich meine wenn srand() nur 1mal aufgerufen werden soll, dann soll er NICHT innerhalb der Methode zufall() stehen, richtig?

    Richtig. 🙂

    P.S. Ist zufall() jetzt endlich als freie Funktion implementiert? :p



  • Michi8080 schrieb:

    ich meine wenn srand() nur 1mal aufgerufen werden soll, dann soll er NICHT innerhalb der Methode zufall() stehen, richtig?

    Das habe ich doch bereits geschrieben.. 🙄



  • also stell ich mir bis jetzt zwei FRAGEN :
    1. wie ändere ich zufall() in freie Funktion?
    Also eine freie Funktion stelle ich mir ohne Scope-Operator einfach mit

    int zufall(int);
    

    vor.
    Die Methode wird dann zu Funktion und kann somit auch nicht unter private in der Klasse im Header bleiben. richtig? D.h. ich muss sie noch VOR der Deklaration der Klasse hinschreiben, oder?

    2. wohin verschiebe ich srand() ?
    -> also soll ich echt nach main() suchen? Ich bin mir zu 99% sicher das die initialisierung von der Klasse an der ich arbeite nur 1 mal durchgeführt wird.

    DAAAAAAAAAAANKE fürs lesen 🙂



  • Michi8080 schrieb:

    Also eine freie Funktion stelle ich mir ohne Scope-Operator einfach mit

    int zufall(int);
    

    vor.

    Genau.

    Michi8080 schrieb:

    Die Methode wird dann zu Funktion und kann somit auch nicht unter private in der Klasse im Header bleiben. richtig? D.h. ich muss sie noch VOR der Deklaration der Klasse hinschreiben, oder?

    Nicht unbedingt davor, einfach im Header. Wenn sie nur lokal in der Implementierungsdatei (.cc) verwendet wird, kannst du sie auch erst da deklarieren. Aber definieren auf jeden Fall erst da.

    Michi8080 schrieb:

    2. wohin verschiebe ich srand() ?
    -> also soll ich echt nach main() suchen? Ich bin mir zu 99% sicher das die initialisierung von der Klasse an der ich arbeite nur 1 mal durchgeführt wird.

    Wenn du dir fast sicher bist, kannst du srand() auch dort aufrufen. Du kannst ja mit Standardausgaben prüfen, ob der Teil mehr als einmal aufgerufen wird...



  • versteh ich es richtig das ich aus aktuell :

    int CommonPartSublayerScheduling::zufall(int a) {
    
            int r = 0;
            srand( (unsigned) time(NULL) ) ;
            for (int i=0; i<10; i++) {
            r = 1 + rand() % 100;
    
            return (r);
            }
    

    die Funktion so reduzieren muss :

    int zufall(int a) {
    
            int r = 0;
            for (int i=0; i<10; i++) {
            r = 1 + rand() % 100;
    
            return (r);
            }
    

    und dann noch :

    srand( (unsigned) time(NULL) ) ;
    

    in die .cc direkt in die Initialisierung kopieren

    und

    in .h statt :

    int zufall(int WERT);
    

    innerhalb der Klasse steht, diese Funktion außerhalb der Klasse platzieren.

    richtig?


Anmelden zum Antworten