Zum Inhalt springen
View in the app

A better way to browse. Learn more.

Fachinformatiker.de

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

PL1994

User
  • Registriert

  • Letzter Besuch

Alle Beiträge von PL1994

  1. Ich habe das nur auf das Wesentliche reduziert. Natürlich muss in der Klasse "Change" noch gespeichert werden, welches Objekt geändert wurde. Da lag nur nicht mein Problem. Das würde ich dann mit Hilfe einer Enumeration machen, deren Member beschreiben, welche Aktion vorgenommen wurde. Eine Variable muss noch den Primärschlüssel speichern. Dann reichen einzelne Integer und Strings völlig und ich brauche nicht Objekte, die den ganzen Datensatz widerspiegeln, in "Change" speichern, obwohl nur ein einzelnes Feld eines Datensatzes geändert werden soll ... Löschen und Einfügen brauche ich nicht, sondern nur die Möglichkeit, eine Aktion rückgängig zu machen. Dafür reichen die Daten aus. Ich wollte nur vermeiden, dass in der Klasse "Value" zwangsläufig immer eine Variable des Wertes "NULL" steht.
  2. Na gut, dann eben anders. Ich werde es wohl jetzt wie folgt machen : #include <ctime> #include <iostream> #include <map> #include <string> using namespace std; class Value { private: enum Type { INTEGER, STRING } type; const int intValue; const string stringValue; public: Value(int value) : type(INTEGER), intValue(value) {} Value(string value) : type(STRING), intValue(NULL), stringValue(value) {} int getIntValue() { return intValue; } string getStringValue() { return stringValue; } }; class Change { private: Value newValue, oldValue; public: Change(Value newValue, Value oldValue) : newValue(newValue), oldValue(oldValue) {} Value getNewValue() { return newValue; } Value getOldValue() { return oldValue; } }; map<time_t, Change> changelog; int main() { changelog.insert(pair<time_t, Change>(time(NULL), Change(Value(1), Value(2)))); changelog.insert(pair<time_t, Change>(time(NULL)+1, Change(Value("string1"), Value("string2")))); for (map<time_t, Change>::iterator i = changelog.begin(); i != changelog.end(); i++) cout << i->first << ": " << i->second.getOldValue().getIntValue() << " -> " << i->second.getNewValue().getIntValue() << " | " << i->second.getOldValue().getStringValue() << " -> " << i->second.getNewValue().getStringValue() << endl; system("pause"); } Das geht prinzipiell zwar, ist aber halt ungünstig, weil bei "Value" immer eine völlig sinnlose Variable gespeichert ist und man später erst mal herausfinden muss, was überhaupt gespeichert werden sollte. Das scheint mir nicht gerade optimal zu sein. Für Verbesserungsvorschläge bin ich also absolut offen EDIT: Nicht fragen, warum da die Variable "type" drin ist. Wollte was anderes versuchen, was aber Quatsch war. Nur vergessen, das rauszulöschen ...
  3. Bevor ich mich mit Smartpointern auseinandersetze, erkläre ich dann wohl erst einmal, was ich mit den Daten vorhabe: Es geht darum, dass der Benutzer zum Beispiel Änderungen an einer TreeView vornehmen kann oder bestimmte Datensätze bearbeitet etc. Diese Daten werden in einer Datenbank gespeichert. Damit jetzt nicht jedes mal, bei jeder noch so kleinen Änderung gleich die Datenbank bearbeitet werden muss, wollte ich ebendiese Änderungen in einem Changelog speichern, um dann, wenn gewünscht, alle auf einmal in die Datenbank zu übertragen. Außerdem sollte man eine Aktion auch noch rückgängig machen können. Diese könnte ich aber bei einer bloßen Änderung an der Datenbank nicht mehr nachvollziehen. Das wären die zwei Hauptfunktionen. Das muss aber eben mit verschiedenen Datentypen gehen ...
  4. Herrlich, das ist besser! Danke nochmal. Aber wie komme ich jetzt hinterher an die Daten aus "Change" wieder heran? Das geht jedenfalls nicht: Change<int> c = (Change<int>)changelog.at(0);
  5. Habe noch etwas anderes ausprobiert. Das geht im Prinzip. Ich kann mir nur fast nicht vorstellen, dass das keine Nachteile mit sich bringen soll: #include <ctime> #include <iostream> #include <map> using namespace std; typedef long Value; class Change { public: Value v1, v2; Change(Value v1, Value v2) : v1(v1), v2(v2) {} }; map<time_t, Change> changelog; int main() { changelog.insert(pair < time_t, Change>(0, Change((Value)"Val1", (Value)"Val2"))); cout << (char*)changelog.at(0).v1 << "\n" << (char*)changelog.at(0).v2 << endl; system("pause"); } Was haltet ihr davon?
  6. Danke dir für die Antwort. Wenn ich das jetzt richtig verstanden habe, meinst du das so: #include <ctime> #include <iostream> #include <map> using namespace std; class AbstractChange { }; class IntChange : public AbstractChange { public: int newVal; int oldVal; IntChange(int newVal, int oldVal) : newVal(newVal), oldVal(oldVal) {} }; class CharChange : public AbstractChange { public: char newVal; char oldVal; CharChange(char newVal, char oldVal) : newVal(newVal), oldVal(oldVal) {} }; map<time_t, AbstractChange> changelog; int main() { changelog.insert(pair < time_t, AbstractChange>(time(NULL), IntChange(0, 0))); } Dann bräuchte ich aber für alle Datentypen eine eigene Klasse, die jeweils eine Änderung von einer Variable dieses Typs behandelt. Das wäre dann noch aufwendiger, als in einer Klasse "Change" von allen Datentypen Variablen für jeweils neu und alt bereitzustellen. Habe ich das falsch verstanden?
  7. Hallo, ich versuche mich gerade an einem Changelog, das, sobald eine Variable eines beliebigen Typs geändert wird, ebendiese Änderung mit einem Timestamp als Key in einer "map" abspeichern soll. Um nicht an einen Datentyp gebunden zu sein, habe ich eine Klasse "Change" als template geschrieben, die jeweils neuen und alten Wert der Variable beinhalten soll (die Variable, auf die sich die Änderung bezieht, wird noch nicht referenziert, was für mein Problem aber auch egal ist). Das ganze nutzt mir natürlich herzlich wenig, wenn ich mich bei der Definition der "map" dann doch auf einen Datentyp festlegen muss. Ich hatte mir das so vorgestellt: #include <ctime> #include <iostream> #include <map> using namespace std; template<class T> class Change { T n; T o; public: Change(T n, T o) : n(n), o(o) {} T getN() { return n; } T getO() { return o; } }; map<time_t, Change< /* ??? */ >> changelog; int main() { changelog.insert(pair < time_t, Change<int>>(time(NULL), Change<int>(0, 0))); } Die mit "???" markierte Stelle ist mein Problem. Kann ich da irgendetwas einsetzen, um den Datentyp, der hinterher tatsächlich verwendet werden soll, noch offen zu lassen oder geht das sowieso nicht? Die einzige Alternative, die mir einfällt, ist "Change" (dann nicht als template) so umzuschreiben, dass die Klasse für alle möglichen Datentypen Variablen für jeweils neu und alt bereitstellt und entsprechende Konstruktoren. Das dürfte aber ziemlich aufwendig werden. Gibt es eine andere (einfachere) Lösung? Gruß PL1994
  8. Wäre möglich ... ja. Wenn ich "string" statt "char*" verwende, sollte es funktionieren (habe es bis jetzt noch nicht an dem richtigen Programm getestet). Danke dir!
  9. Hallo, ich möchte ein paar Datensätze aus einer SQLITE-Datenbank in eine Liste schreiben. Das Auslesen an sich funktioniert, die Liste wird auch initialisiert. Allerdings werden die vorherigen Einträge immer wieder mit dem nächsten Datensatz überschrieben. Die Liste hat am Schluss also die richtige Länge, aber alle Einträge entsprechen dem letzten, der ausgelesen wurde. Hier der Quellcode: list<Country> countriesList; while (sqlite3_step(statements[GET_COUNTRIES]) == SQLITE_ROW) { countriesList.push_back(Country((int)sqlite3_column_int(statements[GET_COUNTRIES], 0), (char *)sqlite3_column_text(statements[GET_COUNTRIES], 1), (char *)sqlite3_column_text(statements[GET_COUNTRIES], 2), (char *)sqlite3_column_text(statements[GET_COUNTRIES], 3))); for (list<Country>::iterator i = countriesList.begin(); i != countriesList.end(); ++i) { Country c = *i; OutputDebugStringA(c.getName()); OutputDebugStringA("\n"); } } sqlite3_reset(statements[GET_COUNTRIES]);Warum klappt das nicht? Gruß PL1994

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.