Undefinierter Integer [gelöst]



  • Naben zusammen,

    kurze Frage: Kann man einem Integer einen nicht definierten Zustand zuweisen. Also quasi wie int x = 1/0. Wenn ich es richtig verstanden habe, geht der NULL Pointer in diese Richtung. Aber anstatt "0" soll eben in folgender Funktion "nicht definiert" ausgegeben werden.

    #include <iostream>
    
    int main()
    {
        int x = NULL;
        std::cout << x;
    
        return 0;
    }
    

    Freue mich auf eure Antworten.

    Gruß,



  • @Richard_Wunsch sagte in Undefinierter Integer:

    NULL

    ist kein Pointer sondern einfach 0.

    Schau dir std::optional an.



  • Integer haben immer einen Wert. Bei floats dagegen gibt es die spezielle Werte "nan" (not a number) und +-inf (+-unendlich), wovon man "nan" oft für ungültig/nicht gesetzt benutzen kann.

    Bei int musst du aber zu Hilfskonstruktionen greifen (wie von @manni66 vorgeschlagen). Meine eigentliche Frage an dich wäre aber, wozu du das benötigst. Ich bestreite nicht, dass man sowas manchmal haben möchte, aber sehr oft kommt das eigentlich nicht vor. Daher wäre es ggf. möglich, dass du dein Problem besser auf eine andere Weise lösen solltest.



  • @Richard_Wunsch NULL steht nur per Definition für einen ungültigen Zeiger.

    Du kannst ihn nicht von einem Zeiger unterscheiden, der wirklich auf die Adresse 0 zeigt.

    Du kannst einen beliebigen Wert aus dem Wertebereich eines int nehmen. z.B. INT_MIN



  • @DirkB sagte in Undefinierter Integer:

    Du kannst ihn nicht von einem Zeiger unterscheiden, der wirklich auf die Adresse 0 zeigt.

    Nur dass es in C++ keine gültigen Zeiger gibt die auf Adresse 0 zeigen. Klar, es gibt Systeme wo an Adresse 0 'was liegt. Du wirst aber nie ein Objekt von C++ erhalten dessen Adresse 0 ist, auch wirst du im Erfolgsfall nie 0 von malloc oder operator new zurückbekommen.

    Von daher ist 0 bei Zeigern wunderbar für "hammer nich" verwendbar.

    Bei Integern, wie in der Frage des OP, ist das natürlich anders. Dort gibt es keinen Wert der so speziell herausstehen würde wie 0 für Zeiger.



  • Ich verwende für so etwas üblicherweise 0 oder std::numeric_limits<std::size_t>::max(), je nachdem was besser passt. Wenn du lieber int benutzen willst und den negativen Bereich nicht brauchst oder, kannst du auch Werte <0 nehmen oder ansonsten auch dafür max(). Den maximalen Wert brauchst du meistens sowieso nicht und wenn doch, nimmst du einfach einen größeren Datentypen.



  • Es gibt das hier
    https://en.cppreference.com/w/cpp/types/numeric_limits/quiet_NaN
    aber das macht eben nur Sinn, für Typen, die tatsächlich auch einen Zustand NaN unterstützen.

    Für INT bekommt man da einfach den Wert 0. Macht also keinen Sinn.

    Wenn du z.B. nur positive ganze Zahlen brauchst, dann nimmst du einfach einen INT und nimmst -1 als "ungültigen" Zustand.



  • @Unterfliege sagte in Undefinierter Integer:

    Wenn du lieber int benutzen willst und den negativen Bereich nicht brauchst oder, kannst du auch Werte <0 nehmen oder ansonsten auch dafür max().

    Bei int würde ich eher min() nehmen. Mit max() würdest du die Asymmetrie zwischen max. nutzbarem negativem Wert und max. nutzbarem positiven Wert nur noch grösser machen - mit min() dagegen würde man sie ausgleichen. Zugegeben, ist jetzt wohl meistens wörscht, aber finde ich konzeptionell irgendwie schöner.



  • Vielen Dank für eure ganzen Antworten! Der konkrete Anwendungsfall ist, dass ich vordefinierten Kategorien Werte zuweisen möchte. Diese sollen in einer .txt Datei gespeichert und bei Bedarf wieder ausgelesen werden. Zur Vereinfachung nur die Input Funktion:

    #include <iostream>
    #include <string>
    #include <fstream>
    
    int getValue (std::string concreteCategory, int inputValue = 0){
        std::cout << concreteCategory <<": ";
        std::cin >> inputValue;
        return inputValue;
    }
    
    int main () {
        std::string categories[4] ={"test", "test1", "test2", "test3"};
        int categoryValue[4];
        std::fstream test;
        for (int i = 0; i<4; i++){
            categoryValue[i] = getValue (categories[i]);
        }
        test.open("test.txt", std::ios::out | std::ios::app);
        for (int i = 0; i<4; i++){
            test << categories[i] << std::endl <<categoryValue[i] << std::endl;
        }
        test.close();
        return 0;
    }
    
    

    Im Anschluss soll mitcategoryValue [] und den konkreten Werten in Abhängigkeit zu den Kategorien gerechnet werden. Wenn ich also eine Kategorie + Wert aus der Rechnung ausschließen möchte, muss der Wert undefiniert bleiben. Negative Zahlen funktionieren deshalb als Ausschlusskriterium nicht. Aber wie vorgeschlagen, kann ich ja einfach einen Float statt eines Integers verwenden.



  • Ich habe deine Version mal modernisiert, damit du eine Orientierung hast, wie man das auch machen kann 😇
    Dein Quellcode ist schon gut, aber es gibt halt immer noch ein paar Dinge, die man besser machen kann, bei jedem Entwickler übrigens 😉 Und manches ist halt auch einfach Geschmackssache. 😁

    #include <iostream>
    #include <string>
    #include <fstream>
    #include <vector>
    
    
    void enterValueForCategory( std::pair<std::string, int> &mypair )
    {
        std::cout << mypair.first <<": ";
        std::cin >> mypair.second;
    }
    
    
    int main () {
        std::vector<std::pair<std::string, int>> CategoryValuePairs = { { "test", 0 }, { "test1", 0 }, { "test2", 0 }, { "test3", 0 } };
        // Values eingeben
        for ( auto &mypair : CategoryValuePairs )
            enterValueForCategory( mypair );
    
        std::ofstream fileOut( "test.txt", std::ios::app );
        if ( !fileOut.good() )
        {
            // Fehlerzustand
            return -1;
        }
    
        // Ausgabe in Datei
        for ( auto &mypair : CategoryValuePairs )
            fileOut << mypair.first << "\n" << mypair.second << "\n";
        return 0;
    }
    
    

    Stichworte:

    • sprechende Funktionsnamen
    • passende Strukturen auswählen ( in dem Fall bietet sich das std::pair regelrecht an )
    • Fehlerzustände prüfen ( z.B. von Dateien )


  • @It0101 Sehr nice, vielen Dank für deine Mühe! An deinen Vorschlägen habe ich erstmal ein bisschen zu knabbern 😃 Und ja.... sprechende Funktionsnamen habe ich immer noch nicht so raus. Die Hinweise auf std::pair und ios::good() sind auch top!



  • @Richard_Wunsch sagte in Undefinierter Integer [gelöst]:

    @It0101 Sehr nice, vielen Dank für deine Mühe! An deinen Vorschlägen habe ich erstmal ein bisschen zu knabbern 😃 Und ja.... sprechende Funktionsnamen habe ich immer noch nicht so raus. Die Hinweise auf std::pair und ios::good() sind auch top!

    ist alles kein MustHave, aber manches ist Nice2Know 😉 Wenn du Fragen hast, immer raus damit.



  • Besser wäre is_open() statt good().



  • @spiri sagte in Undefinierter Integer [gelöst]:

    Besser wäre is_open() statt good().

    Ich glaube bei taufrischen jungfräulichen Stream-Objekten ist das egal. Wenn das Objekt natürlich vorher schonmal benutzt wurde, kann eines der FailBits noch gesetzt sein und man bekommt bei good() false zurück obwohl die Datei offen ist.
    Da ich aber generell keine Stream-Objekte recycle, ist das für mich egal 😉



  • Hm...

    meine erste Intuition wäre hier eigentlich eher eine map von Schlüssel auf Wert gewesen. Wenn der Schlüssel nicht in der map vorkommt, ist der Wert nicht gesetzt. Der von @It0101 vorgeschlagene std::vector<std::pair<std::string, int>> hätte lediglich den Vorteil, dass die Reihenfolge der Werte gleich bleibt. Ansonten würde ich std::map<std::string, int> vorschlagen (oder auch unordered_map). So eine Map könnte man auch problemlos nach json/yaml oder was auch immer schreiben und von da auslesen (geht mit dem vector natürlich auch). Ich würde also eine fertige Bibliothek dafür nehmen.



  • @wob
    In dem geposteten Beispiel sucht er aber nicht gezielt nach Keys/Strings. Daher schien mir die unordered_map unpassend.
    Kann man aber genauso nehmen. In dem Beispiel machts aber funktional keinen Unterschied. Und die Performance vom vector dürfte bei nur 4 Einträgen besser sein, selbst wenn man nach Keys sucht 😉



  • @It0101 Nur noch eine kleine Anmerkung: wenn die Größe zur compile time feststeht und sich nicht ändern soll, würde ich eher std::array empfehlen. Ist dann auch das genaue Equivalent zu dem verwendeten C-Style Array.



  • @Unterfliege sagte in Undefinierter Integer [gelöst]:

    @It0101 Nur noch eine kleine Anmerkung: wenn die Größe zur compile time feststeht und sich nicht ändern soll, würde ich eher std::array empfehlen. Ist dann auch das genaue Equivalent zu dem verwendeten C-Style Array.

    Das sind Details. In der Praxis hab ich noch nie einen passenden Anwendungsfall für std::array gehabt, weil die meisten Sachen in der Serverentwicklung konfigurierbar sind. Daher ist es für Anfänger wesentlich wichtiger, std::vector zu beherrschen.



  • @It0101 sagte in Undefinierter Integer [gelöst]:

    In dem geposteten Beispiel sucht er aber nicht gezielt nach Keys/Strings. Daher schien mir die unordered_map unpassend.

    Naja, das hatte ich anders verstanden. Vordefinierten Kategorien sollen Werte zugewiesen werden - und diese Werte können fehlen.

    Das passt doch exakt zur map: ich muss nachgucken, ob es einen vordef. Wert gibt (map.find) und diesen, wenn vorhanden, dann zuweisen.

    Kann aber natürlich sein, dass das Problem anders gelagert ist. Die "was ist schneller"-Diskussion möchte ich nicht mitführen, weil man hier die für das Problem logisch richtige Datenstruktur wählen sollte.



  • Auf den ersten Blick, denke ich auch, dass std::map besser geeignet ist. Ich würde es gerne nach folgendem Muster benutzen.

    #include <map>
    #include <string>
    #include <iostream>
    
    int main()
    {
        int x;
        int y;
        std::map <std::string, std::map<int,int>> test= {"test",{1,x+y}};
        return 0;
    }
    

    Dabei ist der string der Name der Kategorie, der erste Integer der Wert und der zweite Integer die Formel, nach der gerechnet werden soll. Kann das so theoretisch überhaupt funktionieren und wie initalisiere ich diese Map richtig?