Pointer überprüfen bevor man ihn nutzt.



  • Hallo alle miteinander,

    ich studiere Elektrotechnik und Informationstechnik. Für das Fach SoftwarEngineering müssen wir den Code für eine AufzugsSteuerung entwickeln.

    Da die Ausgänge auf jedem Stockwerk Links ODER Rechts sein können haben wir für die Klasse CEntrance (Modelliert Zugangstür auf den Stockwerken) und CCabindoor (Modelliert die Kabinentür die immer mit der Kabine mitfährt) zwei Maps angelegt um mit deren Hilfe die richtige Türseite zu öffnen und zu schließen. Beide Klassen CEntrance und CCabinDoor erben von der Klasse CDoor die das allgemein Verhalten einer Tür beschreibt (für die Simulation). Die Enumaration für die Ausstiegsseite ist auch dort definiert. Also enum SIDE {LEFT, RIGHT}.
    Die Defintion der Maps sieht wie folgt aus:

    std::map<unsigned short, CEntrance*> m_pEntrances;
    std::map<CDoor::SIDE, CCabinDoor*> m_pCabinDoors;

    Ich habe eine sehr spezifische Frage bezüglich maps und Zeiger. Wenn ich der Kabine sage das sie ihre Türen schliessen soll bevor sie losfährt, mache ich das mit folgenden Befehl:

    m_pCabinDoors[m_pEntrances[currentFloor()]->m_entranceDoor.side()]->close();

    Dieser Befehl erfordert jedoch das ich eine Kabinentüre auf der entsprechenden Seite habe. Für den Extremen Fall das ich mal eine Kabine erzeugen sollte die nur LEFT eine Kabinentür hat aber es auch RIGHT Zugänge auf einem oder mehreren Stockwerken gibt hängt sich mein Code komplett auf, sobald ich einen dieser Stockwerke anfahre. Der Laboringeneur möchte das ich das korrigiere und ich sehe vor lauter Bäumen den Wald nicht 😕

    Ich muss also bevor ich den Zeiger m_pCabinDoors nutze erstmal überprüfen ob auf dieser Seite überhaupt eine Kabinentür existiert.

    Soll ich den kompletten Methodenaufruf: m_pCabinDoors[m_pEntrances[currentFloor()]->m_entranceDoor.side()]->close();
    in eine private Methde umpacken und ein if-Konstukt darum bauen das überprüft ob die Kabinentür exisitiert ?
    Der Laboringeneur meinte die map-methoden: count() und find() könnte ich hier benutzen. Aber dieses Projekt ist meine erste Begegnung mit maps und ich bin ein bisschen von der Syntax überfordert.

    Für anregende Ideen und Beispielcode wäre ich sehr dankbar.
    Falls ihr noch mehr Info´s braucht, lasst es mich wissen.

    LG Luke



  • Luke411 schrieb:

    Ich muss also bevor ich den Zeiger m_pCabinDoors nutze erstmal überprüfen ob auf dieser Seite überhaupt eine Kabinentür existiert.

    Korrekt

    Luke411 schrieb:

    Soll ich den kompletten Methodenaufruf: m_pCabinDoors[m_pEntrances[currentFloor()]->m_entranceDoor.side()]->close();
    in eine private Methde umpacken und ein if-Konstukt darum bauen das überprüft ob die Kabinentür exisitiert ?

    Kannst du machen wenn du magst.
    Oder du packst das "if" mit in die Funktion rein.
    Oder... was den close() Fall angeht vermutlich noch besser: du schreibst dir nen Code der alle vorhandenen "cabin doors" prüft, und alle schliesst die aus welchem Grund auch immer offen sind.
    Was die Sache aber natürlich nur verschiebt, denn bei "open" kannst (solltest/darfst) du das natürlich nicht so machen - kannst ja nicht immer alle Cabin Doors aufmachen.

    Luke411 schrieb:

    Der Laboringeneur meinte die map-methoden: count() und find() könnte ich hier benutzen.

    Und da haben sie Recht 🙂

    Luke411 schrieb:

    Aber dieses Projekt ist meine erste Begegnung mit maps und ich bin ein bisschen von der Syntax überfordert.

    Also...

    m_pCabinDoors[ m_pEntrances[currentFloor()]->m_entranceDoor.side() ]->close();
    ... hm.
    Zerlegen wir das erstmal. In:

    CDoor::SIDE const side = m_pEntrances[currentFloor()]->m_entranceDoor.side();
    m_pCabinDoors[side]->close();
    

    m_pCabinDoors ist deine map.
    m_pCabinDoors[side] ruft den operator[] der map auf.
    Und der macht folgendes: WENN es einen Eintrag für side gibt, dann bekommst du eine Referenz auf diesen Eintrag.
    Und wenn es KEINEN Eintrag für side gibt, dann wird ein neuer angelegt, und du bekommst eine Referenz auf diesen neuen Eintrag!
    Im Falle von Zeigern ist so ein neu angelegter Eintrag dann ein NULL Zeiger. (Den du dann versuchst zu dereferenzieren und deswegen kracht es dann.)

    m_pCabinDoors.count(side) gibt dir die Anzahl der Einträge für side zurück. Bei einer normalen map kann das nur entweder 1 oder 0 sein.
    (Der Grund warum es "count" heisst und nicht "has_key" oder "exists" oder so, hat damit zu tun dass es auch ne multimap gibt. Bei der es dann mehr als nur einen Eintrag mit dem selben Key geben kann. Und da macht "count" dann Sinn. Und damit map und multimap möglichst gleich zu bedienen sind... heissts halt bei der map auch "count".)

    Mit m_pCabinDoors.find(side) ginge es auch, aber mit count() ist es erstmal einfacher, deswegen geh ich da nicht näher darauf ein.

    D.h. du kannst schreiben:

    CDoor::SIDE const side = m_pEntrances[currentFloor()]->m_entranceDoor.side();
    if (m_pCabinDoors.count(side) > 0) // WENN es einen Cabin Door für "side" gibt...
        m_pCabinDoors[side]->close();  // ... dann schlissen wir die mal
    


  • Wenn du map[] für einen Schlüssel aufrufst, der noch nicht in der map gespeichert ist, wird dabei ein neuer Eintrag angelegt. Da du das nicht willst, musst du vorher prüfen, ob überhaupt einer vorhandenen ist.

    Beispielcode http://www.cplusplus.com/reference/map/map/count/



  • Der Vollständigkeit halber trotzdem ein Beispiel mit map::find :

    CDoor::SIDE const side = m_pEntrances[currentFloor()]->m_entranceDoor.side(); 
    std::map<CDoor::SIDE, CCabinDoor*>::iterator pos = m_pCabinDoors.find( side );
    if( pos != m_pCabinDoors.end() )
    {
       pos->second->close();
    }
    


  • Danke an alle,
    besonders Hustbaer.

    Top erklärt, habe nochmal ein bisschen nach geleesen über die count funktion und soweit alles Verstanden.
    Programm funktioniert jetzt wie es soll.
    Ich wäre vermutlich nicht auf die Idee gekommen diese Zeile auseinander zu friemeln.

    Vielen Vielen Vielen Lieben Dank.

    Schöne Grüße aus Frankfurt.


Log in to reply