Problem: Runtime Library
-
@redadmiral sagte in Problem: Runtime Library:
Ich arbeite mit Visual Studio 2013.
OT: Es gibt mittlerweile VS 2017, das den aktuellen Standard implementiert.
-
Vielen Dank ersteinmal für die ganze Hilfe.
Für die studentische Arbeit haben wir mehrere Header- und Quelldateien zur Verfügung gestellt bekommen von denen wir 2 bearbeiten bzw. unserer Quellcode eintragen mussten. Ich finde aber leider immer noch nicht den Fehler und wollte euch hiermit herzlichst bitten mir bei der Fehlersuche zu helfen.
Der Code meiner Quelldatei wäre der folgende#include "Lift.h" // ---------------------------------------------------------------------- // Konstruktor Lift::Lift() { Lift::doorIsOpen = true; engineState = ""; positionSensor = 0; directionDisplay = ""; message = "Lift-Simulator"; }; // ---------------------------------------------------------------------- // Zustandsabfragen // Zustand des Motors, gibt "UP", "DOWN", oder "" zurück string Lift::getEngineState() const { return engineState; }; // Zustand der Tür bool Lift::getDoorIsOpen() const { return doorIsOpen; }; // Zustand der Kontroll-Leuchten // Fahrtrichtungsanzeige, gibt "UP", "DOWN", oder "" zurück string Lift::getDirectionDisplayState() const { return directionDisplay; }; // Positionsanzeige (Kabine und alle Etagen), gibt eine Ziffer 0-9 zurück int Lift::getPositionDisplayState() const { return positionSensor; }; // Kabinen-Anzeige der gewählten Etagen, gibt eine Menge von Ziffern 0-9 zurück set<int> Lift::getCabinDisplaySelectedLevels() const { return cabinDisplaySelectedLevels;; }; // Etagen-Anzeigen der gewünschten Fahrtrichtungen // Der Schlüssel (int) ist eine Ziffer 0-9 // Der Wert (string) ist "UP", "DOWN", "UPDOWN" oder "" map<int, string> Lift::getHallSelectedDirections() const { return hallSelectedDirections;; }; // ---------------------------------------------------------------------- // Positionsmessung, position (0-9) gibt die aktuelle Etage an void Lift::setPositionSensor(int position) { for (it = Lift::getCabinDisplaySelectedLevels().begin(); it != Lift::getCabinDisplaySelectedLevels().end(); it++) { if (Lift::toString(*it) == Lift::toString(position)) { Lift::doorIsOpen = true; Lift::engineState = ""; Lift::cabinDisplaySelectedLevels.erase(position); if (Lift::getCabinDisplaySelectedLevels().empty() == true && Lift::getHallSelectedDirections().empty() == true) { Lift::directionDisplay = ""; message = "(keine weiteren fahrten) Bitte aussteigen, Sie sind im " + Lift::toString(position) + ". Stock"; } } message = "(in) aktueller Stock: " + Lift::toString(position) + " Ziel: " + Lift::toString(*it); } for (mapIt = Lift::getHallSelectedDirections().begin(); mapIt != Lift::getHallSelectedDirections().end(); mapIt++) { if (Lift::toString((*mapIt).first) == Lift::toString(position)) { Lift::doorIsOpen = true; Lift::engineState = ""; Lift::hallSelectedDirections.erase(position); if (Lift::getHallSelectedDirections().empty() == true && Lift::getCabinDisplaySelectedLevels().empty() == true) { Lift::directionDisplay = ""; message = "(keine weiteren fahrten) Bitte einsteigen, Sie sind im " + Lift::toString(position) + ". Stock"; } } message = "(out) aktueller Stock: " + Lift::toString(position) + " Ziel: " + Lift::toString((*mapIt).first); } if (engineState == "DOWN" || engineState == "UP") { //Lift::doorIsOpen = false; } else { Lift::doorIsOpen = true; } positionSensor = position; }; // Sensor Türblockierung, wird von außen aufgerufen, sobald niemand // mehr ein- oder aussteigt void Lift::setDoorIsFree() { Lift::doorIsOpen = false; Fahrtrichtungsabfrage(); if (Lift::directionDisplay == "UP"&& doorIsOpen == false) { engineState = "UP"; } if (Lift::directionDisplay == "DOWN"&&doorIsOpen == false) { engineState = "DOWN"; } if (Lift::directionDisplay == "") { engineState = ""; } }; // Kommandos // command ist C0, C1, ..., C9 wenn in der Kabine jemand die entsprechende // Etage angewählt hat // command ist HU0, HU1, ..., HU8 wenn auf der entsprechenden Etage jemand // den Lift für eine Aufwärtsfahrt angefordert hat // command ist HD1, HD2, ..., HD9 wenn auf der entsprechenden Etage jemand // den Lift fr eine Abwärtsfahrt angefordert hat void Lift::setCommand(string command) { if (command == "C0" && getPositionDisplayState() != 0) { Lift::cabinDisplaySelectedLevels.insert(0); } else if (command == "C1" && getPositionDisplayState() != 1) { Lift::cabinDisplaySelectedLevels.insert(1); } else if (command == "C2" && getPositionDisplayState() != 2) { Lift::cabinDisplaySelectedLevels.insert(2); } else if (command == "C3" && getPositionDisplayState() != 3) { Lift::cabinDisplaySelectedLevels.insert(3); } else if (command == "C4" && getPositionDisplayState() != 4) { Lift::cabinDisplaySelectedLevels.insert(4); } else if (command == "C5" && getPositionDisplayState() != 5) { Lift::cabinDisplaySelectedLevels.insert(5); } else if (command == "C6" && getPositionDisplayState() != 6) { Lift::cabinDisplaySelectedLevels.insert(6); } else if (command == "C7" && getPositionDisplayState() != 7) { Lift::cabinDisplaySelectedLevels.insert(7); } else if (command == "C8" && getPositionDisplayState() != 8) { Lift::cabinDisplaySelectedLevels.insert(8); } else if (command == "C9" && getPositionDisplayState() != 9) { Lift::cabinDisplaySelectedLevels.insert(9); } else if (command == "HU0") { if (positionSensor == 0) { Lift::engineState = ""; Lift::doorIsOpen = true; } else { Lift::hallSelectedDirections.insert(pair<int, string>(0, "UP")); } } else if (command == "HU1") { if (positionSensor == 1) { Lift::engineState = ""; Lift::doorIsOpen = true; } else { Lift::hallSelectedDirections.insert(pair<int, string>(1, "UP")); } } else if (command == "HU2") { if (positionSensor == 2) { Lift::engineState = ""; Lift::doorIsOpen = true; } else { Lift::hallSelectedDirections.insert(pair<int, string>(2, "UP")); } } else if (command == "HU3") { if (positionSensor == 3) { Lift::engineState = ""; Lift::doorIsOpen = true; } else { Lift::hallSelectedDirections.insert(pair<int, string>(3, "UP")); } } else if (command == "HU4") { if (positionSensor == 4) { Lift::engineState = ""; Lift::doorIsOpen = true; } else { Lift::hallSelectedDirections.insert(pair<int, string>(4, "UP")); } } else if (command == "HU5") { if (positionSensor == 5) { Lift::engineState = ""; Lift::doorIsOpen = true; } else { Lift::hallSelectedDirections.insert(pair<int, string>(5, "UP")); } } else if (command == "HU6") { if (positionSensor == 6) { Lift::engineState = ""; Lift::doorIsOpen = true; } else { Lift::hallSelectedDirections.insert(pair<int, string>(6, "UP")); } } else if (command == "HU7") { if (positionSensor == 7) { Lift::engineState = ""; Lift::doorIsOpen = true; } else { Lift::hallSelectedDirections.insert(pair<int, string>(7, "UP")); } } else if (command == "HU8") { if (positionSensor == 8) { Lift::engineState = ""; Lift::doorIsOpen = true; } else { Lift::hallSelectedDirections.insert(pair<int, string>(8, "UP")); } } else if (command == "HD1") { if (positionSensor == 1) { Lift::engineState = ""; Lift::doorIsOpen = true; } else { Lift::hallSelectedDirections.insert(pair<int, string>(1, "DOWN")); } } else if (command == "HD2") { if (positionSensor == 2) { Lift::engineState = ""; Lift::doorIsOpen = true; } else { Lift::hallSelectedDirections.insert(pair<int, string>(2, "DOWN")); } } else if (command == "HD3") { if (positionSensor == 3) { Lift::engineState = ""; Lift::doorIsOpen = true; } else { Lift::hallSelectedDirections.insert(pair<int, string>(3, "DOWN")); } } else if (command == "HD4") { if (positionSensor == 4) { Lift::engineState = ""; Lift::doorIsOpen = true; } else { Lift::hallSelectedDirections.insert(pair<int, string>(4, "DOWN")); } } else if (command == "HD5") { if (positionSensor == 5) { Lift::engineState = ""; Lift::doorIsOpen = true; } else { Lift::hallSelectedDirections.insert(pair<int, string>(5, "DOWN")); } } else if (command == "HD6") { if (positionSensor == 6) { Lift::engineState = ""; Lift::doorIsOpen = true; } else { Lift::hallSelectedDirections.insert(pair<int, string>(6, "DOWN")); } } else if (command == "HD7") { if (positionSensor == 7) { Lift::engineState = ""; Lift::doorIsOpen = true; } else { Lift::hallSelectedDirections.insert(pair<int, string>(7, "DOWN")); } } else if (command == "HD8") { if (positionSensor == 8) { Lift::engineState = ""; Lift::doorIsOpen = true; } else { Lift::hallSelectedDirections.insert(pair<int, string>(8, "DOWN")); } } else if (command == "HD9") { if (positionSensor == 9) { Lift::engineState = ""; Lift::doorIsOpen = true; } else { Lift::hallSelectedDirections.insert(pair<int, string>(9, "DOWN")); } } Fahrtrichtungsabfrage(); if (Lift::directionDisplay == "UP"&& doorIsOpen == false) { engineState = "UP"; } else if (Lift::directionDisplay == "DOWN"&&doorIsOpen == false) { engineState = "DOWN"; } else if (Lift::directionDisplay == "") { engineState = ""; } }; void Lift::Fahrtrichtungsabfrage() { int schleife = 0; set<int>::iterator it; //Fahrrichtungsbestimmung für die Abwärtsbewegung if (Lift::directionDisplay == "DOWN") { Lift::directionDisplay = ""; it = Lift::getCabinDisplaySelectedLevels().begin(); if (Lift::getCabinDisplaySelectedLevels().begin() != Lift::getCabinDisplaySelectedLevels().end() && *it < positionSensor)Lift::directionDisplay = "DOWN"; for (schleife = 0; schleife<positionSensor; schleife++) { if ((Lift::getHallSelectedDirections())[schleife] == "DOWN" || (Lift::getHallSelectedDirections())[schleife] == "UPDOWN") Lift::directionDisplay = "DOWN"; }; }; //Fahrrichtungsbestimmung für die Aufwärtsbewegung if (Lift::directionDisplay == "UP") { Lift::directionDisplay = ""; for (it = Lift::getCabinDisplaySelectedLevels().begin(); it != Lift::getCabinDisplaySelectedLevels().end(); it++) if (*it>positionSensor)Lift::directionDisplay = "UP"; for (schleife = positionSensor; schleife<10; schleife++) { if ((Lift::getHallSelectedDirections())[schleife] == "UP" || (Lift::getHallSelectedDirections())[schleife] == "UPDOWN")Lift::directionDisplay = "UP"; }; }; //Fahrrichtungsbestimmung wenn noch keine Richtung festgelegt wurde if (Lift::directionDisplay == "") { // Innenkabine for (it = Lift::getCabinDisplaySelectedLevels().begin(); it != Lift::getCabinDisplaySelectedLevels().end(); it++) { if (*it<positionSensor)Lift::directionDisplay = "DOWN"; if (*it>positionSensor)Lift::directionDisplay = "UP"; }; for (schleife = 0; schleife<10; schleife++) { //Aussenkabine if ((Lift::getHallSelectedDirections())[schleife] != "" && positionSensor > schleife) Lift::directionDisplay = "DOWN"; if ((Lift::getHallSelectedDirections())[schleife] != "" && positionSensor < schleife) Lift::directionDisplay = "UP"; }; }; } string Lift::toString(int number) { stringstream out; out << number; return out.str(); }
Der Code meiner Headerdatei wäre hingegen dieser hier.
#include <iostream> #include <set> #include <map> #include <string> #include <sstream> using namespace std; class Lift { public: // ---------------------------------------------------------------------- // Konstruktor Lift(); // ---------------------------------------------------------------------- // Zustandsabfragen // Zustand des Motors, gibt "UP", "DOWN", oder "" zurück string getEngineState() const; void setEngineState(string state); // Zustand der Tür bool getDoorIsOpen() const; void checkDoor(int position); // Fahrtrichtungsanzeige, gibt "UP", "DOWN", oder "" zurück string getDirectionDisplayState() const; // Positionsanzeige (Kabine und alle Etagen), gibt eine Ziffer 0-9 zurück int getPositionDisplayState() const; // Kabinen-Anzeige der gewählten Etagen, gibt eine Menge von Ziffern 0-9 zurück set<int> getCabinDisplaySelectedLevels() const; // Etagen-Anzeigen der gewünschten Fahrtrichtungen // Der Schlüssel (int) ist eine Ziffer 0-9 // Der Wert (string) ist "UP", "DOWN", "UPDOWN" oder "" map<int, string> getHallSelectedDirections() const; void chooseDirection(int position); // ---------------------------------------------------------------------- // Input von aussen // Positionsmessung, position (0-9) gibt die aktuelle Etage an void setPositionSensor(int position); // Sensor Türblockierung, wird von au?en aufgerufen, sobald niemand // mehr ein- oder aussteigt void setDoorIsFree(); // Kommandos // command ist C0, C1, ..., C9 wenn in der Kabine jemand die entsprechende // Etage angewählt hat // command ist HU0, HU1, ..., HU8 wenn auf der entsprechenden Etage jemand // den Lift für eine Aufwärtsfahrt angefordert hat // command ist HD1, HD2, ..., HD9 wenn auf der entsprechenden Etage jemand // den Lift für eine Abwärtsfahrt angefordert hat void setCommand(string command); void Fahrtrichtungsabfrage(); // ---------------------------------------------------------------------- // Kontrollmittelungen zum Debuggen; Nutzung ist optional string message; // implementierte Funktionen und Variablen string toString(int number); private: bool doorIsOpen; string engineState; int positionSensor; string directionDisplay; int positionDisplay; set <int> cabinDisplaySelectedLevels; map <int, string> hallSelectedDirections; set<int>::iterator it; map<int, string>::iterator mapIt; };
Ich weiß das es viel ist was ich hier möchte also VIELEN DANK schon einmal im Voraus!
-
Lift::getCabinDisplaySelectedLevels().begin(); it != Lift::getCabinDisplaySelectedLevels().end()
begin und end sind aus zwei verschiedenen sets, daLift::getCabinDisplaySelectedLevels()
eine Kopie zurück gibt.
-
Ui, das is sicher auch was Performance angeht voll super.
-
@manni66
Hättest du eventuell eine einfache Lösungsmöglichkeit für mich parat?
Auch hier wieder vielen Dank für die ganze Unterstützung!
-
@redadmiral
Benutze die Membervariable, nicht die Getterfunktion. Das gilt natürlich auch für die map ein paar Zeilen später.Wann immer du eine solche Getterfunktion benutzen musst: rufe sie nur einmal auf und weise das Ergebnis einer lokalen Variablen zu. Anschließend benutze diese Variable.
-
@manni66
Vielen Dank nochmals für deine Hilfe, jedoch bekomme ich es leider immer noch nicht hin. Ich bin leider absoluter Anfänger im Programmieren und mir geht leider auch etwas die Zeit aus. Könntest du mir eventuell, falls es keine zu großen Umstände macht, beispielhaft zeigen, wie ich das ausgebessert bekomme? Am liebsten wäre mir natürlich wenn du es mir an meinem Bsp. direkt zeigen könntest. Bitte entschuldige die Unannehmlichkeiten, aber ich schiebe mittlerweile etwas Panik, da mir das Ganze auch nicht so gut liegt.
-
@redadmiral Da sich keiner Beschwert: Sieht das nur bei mir so ugly aus? Ich meine der halbe Code als normaler Text, dann ein Teil in der codebox? Ist mir jetzt schon bei mehreren Posts hier aufgefallen. Beitrag unten rechts sind drei Punkte, darüber kann man das Posting bearbeiten... Danke!
-
@redadmiral
Nein. Wenn du den Rest tatsächlich selbst programmiert hast ist die Umsetzung trivial.
-
@redadmiral: Falls du mit dem Begriff "Membervariablen" (noch) nichts anfangen kannst, das sind die Variablen in der Headerdatei unterhalb von "private:" (zumindestens in deiner gezeigten Headerdatei).
-
@dirkski sagte in Problem: Runtime Library:
@redadmiral Da sich keiner Beschwert: Sieht das nur bei mir so ugly aus? Ich meine der halbe Code als normaler Text, dann ein Teil in der codebox? Ist mir jetzt schon bei mehreren Posts hier aufgefallen. Beitrag unten rechts sind drei Punkte, darüber kann man das Posting bearbeiten... Danke!
Ah. Viel Besser. Danke und Guten Morgen.
-
@redadmiral sagte in Problem: Runtime Library:
Könntest du mir eventuell, falls es keine zu großen Umstände macht, beispielhaft zeigen, wie ich das ausgebessert bekomme? Am liebsten wäre mir natürlich wenn du es mir an meinem Bsp. direkt zeigen könntest. Bitte entschuldige die Unannehmlichkeiten, aber ich schiebe mittlerweile etwas Panik, da mir das Ganze auch nicht so gut liegt.Das Problem liegt darin, dass Lift::getCabinDisplaySelectedLevels() eine Kopie des set zurückgibt und bei jedem Aufruf eine neue Kopie erzeugt wird.
for (it = Lift::getCabinDisplaySelectedLevels().begin(); // it ist ein Iterator aus Kopie #1 it != Lift::getCabinDisplaySelectedLevels().end(); // und wird mit end() aus Kopie #2 verglichen it++)
Das ist der Grund für deine Fehlermeldung.
Dazu gibt es jetzt mehrere Lösungen:-
du änderst den Rückgabetyp der Methode getCabinDisplaySelectedLevels() von set<int> auf const set<int>& und gibst eine Referenz auf die Membervariable zurück. Das löst zum einen das Problem der Iteratoren aus verschiedenen Kopien und ist zum anderen auch deutlich performanter, da überhaupt keine Kopie erzeugt wird.
-
du benutzt die Membervariable cabinDisplaySelectedLevels statt der Methode Lift::getCabinDisplaySelectedLevels().
-
du benutzt eine lokale Kopie und benutzt die für die Auswertung
auto local_copy = getCabinDisplaySelectedLevels(); for (it = local_copy.begin(); it != local_copy.end(); it++)
- du benutzt range-based for statt Iteratoren.
for( auto position : getCabinDisplaySelectedLevels() )
Das löst zumindest das Problem der Kopien, da das intern benutzte Iteratorenpärchen auf der gleichen Kopie von set<int> erzeugt werden. Spätestens im weiteren Verlauf der Methode wird´s dann aber unheimlich, weil dann eine Kopie benutzt wird um festzustellen, ob Elemente aus den Originaldaten gelöscht werden sollen.
Vorschlag 1 und 2 sind tatsächlich brauchbar, 3 und 4 eher theoretisch und lösen nur das Problem der Iteratoren aus verschiedenen sets. Dafür werfen sie neue, andere Probleme auf.
Zwei andere Punkte:
- benutze niemals using namespace in Headerdateien! Das hebelt alle Vorteile und Mechanismen von namespaces wieder aus.
- die Notation *Lift::doorIsOpen * innerhalb einer Memberfunktion ist ungewöhnlich und überflüssig. Es gibt Fälle. wo this->doorIsOpen notwendig ist (s.u.), das ist bei dir aber nicht der Fall.
void Lift::set_door_status( bool doorIsOpen ) { // Qualifizierung per this ist notwending, um Mehrdeutigkeit aufzulösen this->doorIsOpen = doorIsOpen; }
-
-
@docshoe
Vielen Dank für deine Hilfe! Aber leider bekomme ich das Ganze immer noch nicht zum Laufen. Ich sitze da jetzt schon den ganzen Tag dran, aber der einzige ersichtlich Fortschritt war bisher, dass das Programm nicht sofort die Fehlermeldung ausgewurfen hat, sonder einen Augenblick gewartet hat. Ich probiere da heute schon seit gut 5 h herum und versuche deine Lösungsvorschläge umzusetzen. Ich komme aber leider nicht mehr klar oder ich mache irgendetwas falsch.
Ich würde am liebsten deinen 1. Lösungsweg umsetzen, aber weder den noch einen anderen bekomme ich zum Laufen. Könntest du mir eventuell kritische Codepassagen ausbessern?
Das ist unverschämt soetwas zu fragen, aber ich weiß echt nicht mehr weiter.
Trotzdem nochmal vielen Dank an alle Unterstützer bisher! Ich weiß ich bin ein harter Fall.
-
Du mußt das selbstverständlich nicht nur für das
std::set<>
sondern auch für diestd::map<>
umsetzen.Am besten kommentiere ersteinmal den unteren Teil des Codes von
setPositionSensor
aus und wenn das für 'std::set<>' funktioniert, kommentierst du den 'std::map<>' Teil wieder ein und änderst diesen dann entsprechend ab!