StringList und Objekte



  • Da die Strings aber schon durch AddObject einen Verweis zum Objekt haben, hab ich eben mal nachgesehen und festgestellt, dass ich nur noch wissen muss, welche Strings auf ein Objekt verweisen. So kann ich diesen Befehl benutzen:

    Die Methode IndexOfObject gibt den Index des ersten Strings in der Liste zurück, dem ein bestimmtes Objekt zugeordnet ist.

    virtual int __fastcall IndexOfObject(System::TObject* AObject);

    Damit kann ich doch an sich schon was anfangen. Damit bastle ich jetzt mal ein wenig herum.



  • Hallo

    IndexOfObject wird dir in deinem Fall nichts bringen, denn dann mußt du das betreffende Objekt bereits haben, und bekommst nur den Index in der Liste.

    Wenn du Name und Vorname als Schlüssel zusammenpackst, kannst du wie Braunstein gesagt hat std::map nehmen

    #include <map>
    
    std::map<AnsiString, TPerson *> PersonMap; // Deklaration einer Personen-Map
    
    TPerson *Person = new TPerson("Heinz", "Mueller"); // neues Objekt für Map erschaffen
    // Zwischenspeicher für Map-Insert, 
    // <Person->Vorname + Person->Nachname> ist der Key, Person der Wert hinter dem Key
    std::map<AnsiString, TPerson *>::value_type MapValue(Person->Vorname + Person->Nachname, Person); 
    PersonMap.insert(MapValue); // Wertepaar in Map einfügen
    ...
    AnsiString Vorname = "Heinz";
    AnsiString Nachname = "Mueller";
    std::map<AnsiString, TPerson *>::iterator Ergebnis; // Rückgabewert beim Suchen eines Keys
    Ergebnis = PersonMap.find(Vorname + Nachname); // Key suchen
    // Wenn Key gefunden, Wert behandeln
    if (Ergebnis != PersonMap.end())
    {
      ShowMessage("Gefunden : " + Ergebnis->second->Nachname + ", " + Ergebnis->second->Vorname);
      }
    

    bis bald
    akari



  • Der Vollständigkeit halber noch eine Variante ohne map und ohne Pointer. Hier wird vector als Container und find_if zu Suchen verwendet. Diese Variante ist bei großen Datenmengen und häufigen Suchen nicht sonderlich effizient. Dann aber würde sich sowieso eine Datenbank anbieten.
    Ich erwähne das hier nur weil ich in meinem BCB5 öfters Probleme mit map habe und dann meistens die unten gezeigte Lösung verwende.

    #include <vcl.h>
    #pragma hdrstop
    
    #include <iostream>
    #include <vector>
    #include <functional>
    #include <algorithm>
    using namespace std;
    
    // zu speichernde Struktur (oder Klasse)
    struct Person
    {
    	AnsiString vorname;
    	AnsiString nachname;
    	int alter;
    // weitere beliebige Daten
    	Person() : vorname(""), nachname(""), alter(0) {}   // Default-Konstruktor
    	Person( const AnsiString &vn, const AnsiString &nn, int a ) // ein möglicher weiterer Konstruktor
    		: vorname(vn), nachname(nn), alter(a) {}
    };
    
    // Hilfsstruktur für find_if (Funktor)
    struct Person_find : public unary_function<Person,AnsiString>
    {
        AnsiString name;
        Person_find(const AnsiString &suchname){name = suchname;}  // Konstruktor
    // Funktor in dem der Vergleich durchgeführt wird
        bool operator()(const Person & object)
        {
            AnsiString temp = object.vorname + object.nachname; 
    		return temp == name;
        }
    };
    //---------------------------------------------------------------------------
    
    int main () 
    {
    // Erzeugung des Vektors mit Testdaten
    	vector<Person> testvect;
    	testvect.push_back(Person("Frank", "Mueller", 20));
    	testvect.push_back(Person("Karl",  "Maier", 22));
    	testvect.push_back(Person("Torsten", "Schulz", 77));
    // Hilfsiterator um Ergebnis von find_if besser auswerten zu können
    	vector<Person>::iterator find;
    // Suchstring
    	AnsiString findname = "Frank";
    	findname += "Mueller";
    // Suche
    	find = find_if(testvect.begin(), testvect.end(), Person_find(findname));
    
    	if( find != testvect.end())
                     cout << "gefunden" << endl;
    	else 	 cout << "nicht gefunden" << endl;
    
    	cin.get();
    	return 0;
    }
    

    Ciao



  • Hallo

    Ich erwähne das hier nur weil ich in meinem BCB5 öfters Probleme mit map habe

    Echt? Ich hab auch den BCB5, und bei mir habe ich keine Probleme. Was genau tritt bei dir auf?

    bis bald
    akari



  • Wenn ich map in dll's verwende crasht es häufiger beim Aufruf des Destruktors von map (also z. Bsp. beim Beenden des Programmes oder Entladen der dll). Meistens so etwas unspezifisches wie "Access violation at address 0000000".
    Ich hatte nach dem ersten Auftreten erst alle Borland spezifischen Sachen entfernt (AnsiString). Das brachte aber nichts. Erst nachdem ich map durch vector + find_if ersetzt hatte lief es wieder. Seitem hatte ich keine derartigen Abstürze mehr.



  • Das mit dem sd::map sieht gut aus... da hock ich mich gleich mal dran. Vielleicht muss ich ja auch einfach eine neue Funktion schreiben, die die Suche beherrscht.

    Oder kann man einen vorhandenen Befehl umschreiben, damit dieser dann mehr kann ? Vielleicht hat schon jemand sowas mit dem Umschreiben schon gemacht und hat da ein paar Ansätze.



  • Oder kann man einen vorhandenen Befehl umschreiben, damit dieser dann mehr kann ?

    😕

    Meinst du Objekte ????
    Du kannst Klassen ableiten und mit eigenen Methoden erweitern falls es das ist was du meinst.



  • IndexObjekt = MeineListe->IndexOfObject(personendaten);
    

    Damit kann ich einen Index aufs Objekt bekommen. Brauch ich jetzt einen cast um das machen, um auf die Werte des Objekts zurückgreifen zu können ?

    Und nochmal ich soll es mit StringList machen auch wenn Vector schöner wäre !



  • Hallo,

    Du willst ja dann sicher über

    MeineListe->Objects[IndexObjekt]
    

    auf dein Objekt zugreifen. Ich kenne nun den Typ von personendaten nicht.
    Wenns von TObject abgeleitet ist geht ein static_cast, wenn nicht, nur ein reinterpret_cast. Wie hast du personendaten denn in deine StringList gebracht und warum mußt du sie verwenden.

    Ciao



  • Also ich muss sie verwenden, damit ich mal die ganzen Facetten beim Programmieren mit der StringList lerne und aus dem Grund soll ich auch nix anderes nehmen.

    class Person : public TObject
    {
      private:
      AnsiString vorname;
      AnsiString nachname;
    
      public:
      Person(); 
      AnsiString getvorname();
      AnsiString getnachname();
      void setvorname(AnsiString vorname);
      void setnachname(AnsiString nachname);
      void zeigevorname();
      void zeigenachname();
    }
    

    Das ist meine Klasse, die von TObjekt erbt.

    for (i = 0; i < Anzahl/2; i++)
      {
        /* Hier werden die Daten für die Objekte eingegeben.
        Dabei wird immer ein neues Objekt erzeugt, wenn man
        bei der If-Abfrage durchkommt. Wenn dies überstanden
        ist, dann kann man auch andere Anweisungen noch einä-
        bringen. */
        Person *personendaten = new Person;
    
        //MeineListe->Add(zahl1);
        personendaten->setvorname(MeineListe->Strings[j]);
        j++;
        //MeineListe->Add(zahl);
        personendaten->setnachname(MeineListe->Strings[j]);
        j++;
        vorname = personendaten->getvorname();
        nachname = personendaten->getnachname();
    
        Datenbank->AddObject(vorname+" "+nachname, personendaten);
        person++;
        personendaten->zeigevorname();
        personendaten->zeigenachname();
    .....
    

    Da gehts auch noch weiter muss man dazu sagen 😉



  • Was willst du denn mit IndexObjekt machen ? Immerhin mußt du das Object ja schon kennen um den Index zu erhalten. Dieser Index ist eigentlich nur nützlich um herauszubekommen ob das Objekt in der Liste ist bzw. um den dazugehörigen String zu bekommen. In beiden Fällen ist ein Cast unnötig.



  • Also ich will ja eigentlich die Namen in der Liste suchen, wobei ich am liebsten das über die Werte der Objekte machen würde.
    Später in der ausgebauten Version will ich nach Vornamen und Nachnamen sortieren und dann auch andere Daten implementieren, wie Wohnort, aber im wesentlichen will ich jetzt erstmal nur Suchen nach Namen und dabei ein wenig mit den Objektern handhaben !



  • Wenn du Namen und Vornamen hast geht die Suche einfacher über

    int index = MeineListe->IndexOf(vorname+" "+nachname);
    

    Dann hast du den Index und kannst auf das dahinter liegende Objekt zugreifen.
    Wenn du nur Teilinformationen hast, bleibt dir wohl nichts anderes übrig als die gesamte Liste durchzugehe und die entsprechenden Objekte zu vergleichen. Bei Mehrdeutigkeiten geht es sowieso nicht anders.
    Nimms mir nicht übel, aber ich halte TStringList für ungeeignet, für das was du vorhast. Prinzipiell willst du ja eine Datenbank nachprogrammieren.



  • Sodele nun hab ich halt alles eingelesen und was mach ich nun, wenn ich 3 Leute habe, die "Müller" oder "Schmidt" heißen.
    Wie gehe ich da vor und was muss ich beachten ?

    Eigene Überlegung:
    Eigentlich müsste ich dann ja schauen, wieviele Personen es mit dem Namen gibt und dann nochmal den Vornamen vergleichen, damit ich sehen kann, ob es da Unterschiede gibt.

    Wie geht man da am Besten und sinnvollsten vor ?


Anmelden zum Antworten