set<int>mySet: Wie erstes Element in "int" speichern?



  • using namespace std;
    
    set<int>mySet;
    
    mySet.insert(7);
    mySet.insert(3);
    mySet.insert(14);
    
    int erstesElement = mySet.beginn(); // Fehler
    

    So ein "set" scheint sehr habgierig zu sein, "rein" gehts wie Butter, aber "raus" wirds kompliziert oder? 😋

    Wie läßt sich am einfachsten nur das erste Element des "sets" in einen "int" speichern?



  • Dereferenziere den Iterator, den dir begin() liefert.



  • Bin leider Anfänger und weiß nicht wie ich das set dereferenzieren soll. Kannst Du mir anhand des Beispiels bitte kurz zeigen wie es geht?

    int erstesElement = ?
    

    In den Beispielen im Internet wird das Ergebnis immer über "cout" ausgegeben. Da "cout" aber immer selbst den Typ wandelt, komme ich damit nicht weiter.



  • #include <set>
    #include <iostream>
    
    int main()
    {
        std::set<int> foo;
        foo.insert( 1 );
        foo.insert( 2 );
        foo.insert( 3 );
        foo.insert( 4 );
    
        for( std::set<int>::iterator iter( foo.begin() ); iter != foo.end(); ++iter )
        {
            std::cout << *iter << "\n";
        }
        for( const auto& iter : foo ) //c++11
        {
            std::cout << iter << "\n";
        }
    }
    


  • Danke für den Code. Aber genau da liegt mein Verständnis Problem. Ich möchte es nicht über "cout" ausgeben, sondern in einen int speichern. Auch möchte ich nicht durch das gesammte set iterieren sondern brauche einfach nur das erste Element.

    int erstesElement = ?
    

    Wie gesagt bin ich Anfänger, besonders was die STL und Container anbelangt. Geht es vielleicht einfacher mit

    int firstElement = mySet.find(x)
    

    Denn die Größe von x ist mir bekannt.


  • Mod

    Ein Iterator ist so etwas wie ein Verweis. Du hast vielleicht schon einmal etwas von Zeigern gehört. Ein Zeiger ist auch eine Art Iterator (aber der set-Iterator ist kein Zeiger!). Das heißt, das begin des Sets ist nicht das erste Element des Sets sondern ein Verweis auf das erste Element. Mit "Dereferenzieren" ist gemeint, dass man einem Verweis folgt. In C++ geht dies traditionell mit einem vorangestelltem Sternchen ( * ), das hat man sich so bei den Zeigern abgeguckt und Iteratoren im allgemeinen machen das auch so.

    Also hier: int erstesElement = *mySet.begin();

    Es gibt auch noch eine andere Methode mittels des Operators[], also Indexzugriff, wie du ihn vielleicht schon bei Arrays/Vectoren gesehen hast. Das ist praktisch eine Abkürzung: foo[i] ist in der Regel das gleiche wie *(foo + i) . Das funktioniert aber nicht mehr für alle Typen von Iteratoren. Der Set-Iterator kann das nicht, normale Zeiger und Vector-Iteratoren können es.

    P.S.: Ich hoffe, das ist kein Programm, bei dem es bloß darum geht, das kleinste Element einer Menge zu finden. Das ginge auch deutlich einfacher.



  • int erstesElement= *(mySet.begin());
    

    begin() holt einen Iterator(fühlt sich an wie Zeiger) aufs erste Element. Und * schaut nach, welcher int da wohnt, wo der Iterator hinzeigt.



  • int erstesElement = *mySet.begin();
    

    Ich sitze wohl schon zu lange vor der Kiste und suche nach der Lösung. Mir wird schwindelig - so einfach ist das! Funktioniert einwandfrei!

    Bei der Suche im Netz fand ich immer wieder:

    int erstesElement = *(MySet.begin());
    oder
    int* erstesElement = *(MySet.begin());
    oder
    int erstesElement = (*MySet.begin());
    oder
    int *erstesElement = (*MySet.begin());
    

    Die alle unter Visual Studio 2013 nicht laufen. War schon völlig am verzweifeln.

    Vielen Dank für die Hilfe!

    P.S.: Noch eine Frage: Wie erhalte ich hier beim Schreiben im Forum statt "Code" als Überschrift des Quellcodes das Wort "C++"?



  • mireiner schrieb:

    Bei der Suche im Netz fand ich immer wieder:

    int erstesElement = *(MySet.begin());
    oder
    int* erstesElement = *(MySet.begin());
    oder
    int erstesElement = (*MySet.begin());
    oder
    int *erstesElement = (*MySet.begin());
    

    Die alle unter Visual Studio 2013 nicht laufen. War schon völlig am verzweifeln.

    Die * nach int haben geschadet, willst ja einen int anlegen und keinen Zeiger auf int. Die Klammen mehr haben nicht geschadet. Ich hab ja auch Schmuck-Klammern gesetzt. Was aber schadet, ist wenn Du MySet statt mySet oder beginn() statt begin() schreibst.



  • SeppJ schrieb:

    Ich hoffe, das ist kein Programm, bei dem es bloß darum geht, das kleinste Element einer Menge zu finden. Das ginge auch deutlich einfacher.

    Jein, mein "set" wechselt seinen Inhalt oft während der Laufzeit. Da "set" immer automatisch sortiert, ist es für mich wichtig zu wissen, ob das erste Element ein Integer mit Wert 0 ist. 0 ist dabei immer das kleinste ELement. Damit kann ich einen grundsätzlichen Zustand über den Inhalt von "set" abfragen.

    So vermutete ich, daß diese Abfrage die schnelleste und einfachste Lösung wäre:

    int erstesElement = *mySet.begin();
    

    Danke für die ausführliche Erklärung! Ich kannte das Symbol * in C++ bislang nur als Pointer. Was Dereferenzieren heißt, habe ich jetzt erst gelernt. 🙂



  • SeppJ schrieb:

    Ich hoffe, das ist kein Programm, bei dem es bloß darum geht, das kleinste Element einer Menge zu finden. Das ginge auch deutlich einfacher.

    Wie würde denn der deutlich einfachere Weg lauten, das kleinste Element eines "set" zu finden?


  • Mod

    mireiner schrieb:

    SeppJ schrieb:

    Ich hoffe, das ist kein Programm, bei dem es bloß darum geht, das kleinste Element einer Menge zu finden. Das ginge auch deutlich einfacher.

    Wie würde denn der deutlich einfachere Weg lauten, das kleinste Element eines "set" zu finden?

    Das kleinste Element eines sets zu finden ist so schon richtig. Mit "Menge" meinte ich hier eine allgemeine Wertemenge, nicht die Datenstruktur "set" (auch wenn "set" übersetzt wird als "Menge"). Denn der Umweg über die Datenstruktur set, um das kleinste Element einer Wertemenge zu finden ist sehr umständlich. Da geht man einfacher die Wertemenge durch und merkt sich das jeweils kleinste Element. Das gibt's auch schon fertig in der Standardbibliothek.



  • Verstehe, dann kann ich das Thema endlich als gelöst betrachten und dank der Hilfe hier zufrieden in die heia fallen. 🙂



  • volkard schrieb:

    int erstesElement= *(mySet.begin());
    

    begin() holt einen Iterator(fühlt sich an wie Zeiger) aufs erste Element. Und * schaut nach, welcher int da wohnt, wo der Iterator hinzeigt.

    Aber Vorsicht, das funktioniert nur wenn begin() auch auf etwas verweist(also die Menge nicht leer ist) und damit mySet.begin() != mySet.end() ist.



  • Folgeproblem:

    int letztesElement = *mySet.end(); Fehlermeldung: "set iterator not dereferenceable"
    

    Gibt es eine andere Möglichkeit an die in "mySet" gespeicherte letzte int Variable zu kommen?





  • Ich hatte es jetzt so gelöst. Ist aber nicht sehr schön:

    set <int> ::iterator iter;
    iter = mySet.end();
    iter--;
    int letztesElement = *iter;
    

    Das ist natürlich viel besser:

    int letztesElement = *mySet.rbegin();
    

    Danke Volkard!



  • mireiner schrieb:

    Ich hatte es jetzt so gelöst. Ist aber nicht sehr schön:

    set <int> ::iterator iter;
    iter = mySet.end();
    iter--;
    int letztesElement = *iter;
    

    Das ist AFAIK auch falsch.
    end() dekrementieren ist soweit ich weiss nur für vector , list , deque garantiert.


  • Mod

    hustbaer schrieb:

    mireiner schrieb:

    Ich hatte es jetzt so gelöst. Ist aber nicht sehr schön:

    set <int> ::iterator iter;
    iter = mySet.end();
    iter--;
    int letztesElement = *iter;
    

    Das ist AFAIK auch falsch.
    end() dekrementieren ist soweit ich weiss nur für vector , list , deque garantiert.

    ? set hat auch Bidirektionale Iteratoren.



  • Oha. Ich wusste nicht dass bidi Iteratoren garantieren müssen dass end-Dekrement OK ist.


Anmelden zum Antworten