sicheres std::string zu zahl?



  • CStoll schrieb:

    template<typename T>
    T to_numeric(const string& data)
    {
      ostringstream str(data);
      T val;
      str>>val;
      if(!str)
        // Fehlerbehandlung
      return val;
    }
    

    Wie muss ich diese fnk. aufrufen?

    beim dev-c++ kommst der fehler.
    no matching function for call to 'to_numeric(std::string*/&)'

    string str("-100");
    int i = to_numeric(&str);
    cout << ">" << i << endl;
    

    @simon:

    Simon2 schrieb:

    die Frage ist: "Sicher wogegen ?"

    programmabsturz, bufferüberlauf und logikfehler (siehe long und double gleich groß). giebt es da noch mehr?

    Simon2 schrieb:

    Was passiert, wenn man die Funktion mit int aufruft ?

    string str("-100");
    int i = to_numeric(i, str.c_str());
    

    i == -100

    Simon2 schrieb:

    ... oder einem char[sizeof(long)] ?

    soll (darf) so im programmcode nicht vorkommen, da es ein c-string (char array) ist.

    Simon2 schrieb:

    ... oder auf einer Plattform, auf der long und double gleich groß sind ?

    oh, double muss vor long zückgegeben werden. oder worauf wolltest du hinaus?

    Simon2 schrieb:

    oder der Platz nicht reicht, auf den der char-Pointer zeigt ?

    verstehe ich nicht, c ist doch schon init. und end auch.

    Simon2 schrieb:

    Warum sollte man also nicht istringstream nehmen, wie der Standard es anbietet ?

    daß weiss ich im mom. nicht vllt. weniger/schnellerer bin. code. sag du es mir 🙂



  • solito schrieb:

    CStoll schrieb:

    template<typename T>
    T to_numeric(const string& data)
    {
      ostringstream str(data);
      T val;
      str>>val;
      if(!str)
        // Fehlerbehandlung
      return val;
    }
    

    Wie muss ich diese fnk. aufrufen?

    beim dev-c++ kommst der fehler.
    no matching function for call to 'to_numeric(std::string*/&)'

    so:

    string str("-100");
    int i = to_numeric<int>(str);
    cout << ">" << i << endl;
    


  • solito schrieb:

    CStoll schrieb:

    template<typename T>
    T to_numeric(const string& data)
    {
      ostringstream str(data);
      T val;
      str>>val;
      if(!str)
        // Fehlerbehandlung
      return val;
    }
    

    Wie muss ich diese fnk. aufrufen?

    noch gar nicht, wenn du noch keine fehlerbehandlung eingebaut hast.
    ansonsten so:

    int i = to_numeric<int> ("42");
    //oder:
    double d = to_numeric<double> ("12.3");
    

    beim dev-c++ kommst der fehler.
    no matching function for call to 'to_numeric(std::string*/&)'

    du hast auch versucht, einen zeiger zu übergeben. to numeric erwartet aber eine konstante referenz.

    @simon:

    Simon2 schrieb:

    die Frage ist: "Sicher wogegen ?"

    programmabsturz, bufferüberlauf und logikfehler (siehe long und double gleich groß). giebt es da noch mehr?
    du verwendest typsichere stringstreams und std::strings, die sich automatisch um die speicherverwaltung kümmern. da wird dir selten was schlimmes passieren.

    solito schrieb:

    Simon2 schrieb:

    ... oder auf einer Plattform, auf der long und double gleich groß sind ?

    oh, double muss vor long zückgegeben werden. oder worauf wolltest du hinaus?

    jetzt lese ich erst, was denn da deine funktion überhaupt macht. du implementierst eine template funktion, die eine typunterscheidung macht. das problem wird sich dann beim kompilieren zeigen 😉

    wenn du mit strod und strol arbeiten willst, musst du aus deiner template-funktion zwei (normale) überladene funktionen machen.

    nimm die lösung mit stringstream und du ersparst dir deine fallunterscheidung.



  • nun hab ich das prob. verstanden ...

    string str("-100.001");
    float f = to_numeric(f, str.c_str());
    long  l = to_numeric(l, str.c_str());
    cout << "f " << f << endl;
    cout << "l " << l << endl;
    

    danke euch und CStoll für die fnk.



  • queer_boy schrieb:

    beim dev-c++ kommst der fehler.
    no matching function for call to 'to_numeric(std::string*/&)'

    du hast auch versucht, einen zeiger zu übergeben. to numeric erwartet aber eine konstante referenz.

    Das dürfte kein Problem sein - du kannst einen char-Zeiger problemlos in eine konstante std::string-Referenz umwandeln.

    @solito: Bei dir hat der erste Parameter der Funktion keine wirkliche Aufgabe außer den Zieltyp festzulegen - und den kannst du auch explizit angeben, damit es deutlicher wird. Und imho sieht "f=to_numeric<float>(str);" übersichtlicher aus als "f=to_numeric(f,str);" (mal abgesehen davon, daß du nicht immer eine Variable zur Verfügung hast, die du dafür übergeben kannst).



  • solito schrieb:

    ...
    @simon:

    Simon2 schrieb:

    die Frage ist: "Sicher wogegen ?"

    programmabsturz, bufferüberlauf und logikfehler (siehe long und double gleich groß). giebt es da noch mehr? ...

    Klar - "Sicher gegen": Ausspähen, Hacken, falsche Benutzung, Plattformabhängigkeiten, undefiniertes Verhalten, ....

    solito schrieb:

    ...

    Simon2 schrieb:

    Was passiert, wenn man die Funktion mit int aufruft ?

    string str("-100");
    int i = to_numeric(i, str.c_str());
    

    i == -100
    ...

    Meine Frage war nicht, was zufällig auf Deiner Plattform und Deinem Compiler dabei herauskommt, sondern, ob das dann noch sicher und überall so funktioniert, wie Du willst.
    z.B. ist IIRC ist nicht sichergestellt, dass int dieselbe Bytegröße hat wie long oder double (wenn es weder die eine noch die andere Bytegröße hat, wird Deine Funktion einfach so ergebnislos durchlaufen und niemand merkt etwas davon).
    Sowas passiert übrigens recht schnell, weil Funktionstemplates ihren Typ auch automatisch bestimmen und bei verschiedenen Rechnung gerne mal "aus Versehen" implizit auf int gecastet wird (z.B. sobald bei einer Division ein int beteiligt ist).

    solito schrieb:

    ...

    Simon2 schrieb:

    ... oder einem char[sizeof(long)] ?

    soll (darf) so im programmcode nicht vorkommen, ...

    Aha => also schonmal nicht sicher gegen Fehlbenutzung (egal, ob absichtlich oder unabsichtlich).
    Wenn Du sicheren Code produzieren willst, dürfen so simple Stolpersteine nicht dabei sein.

    solito schrieb:

    ...

    Simon2 schrieb:

    ... oder auf einer Plattform, auf der long und double gleich groß sind ?

    oh, double muss vor long zückgegeben werden. oder worauf wolltest du hinaus?
    ...

    Und wie soll das das Problem lösen, wenn Du einen long übergibst (dann aber strod() aufgerufen wird) ?

    solito schrieb:

    ...

    Simon2 schrieb:

    oder der Platz nicht reicht, auf den der char-Pointer zeigt ?

    verstehe ich nicht, c ist doch schon init. und end auch.
    ...

    Verstehe ich auch nicht mehr - war wohl mein Denkfehler.

    Simon2 schrieb:

    Warum sollte man also nicht istringstream nehmen, wie der Standard es anbietet ?

    daß weiss ich im mom. nicht vllt. weniger/schnellerer bin. code. sag du es mir :)[/quote]
    Auch das weiß ich nicht: Ich sehe jedenfalls bei istringstream nur Vorteile ... gerade bzgl. der Sicherheit.
    (Mit "vermuteter Performance" kann ich nichts anfangen).

    Gruß,

    Simon2.



  • CStoll schrieb:

    queer_boy schrieb:

    beim dev-c++ kommst der fehler.
    no matching function for call to 'to_numeric(std::string*/&)'

    du hast auch versucht, einen zeiger zu übergeben. to numeric erwartet aber eine konstante referenz.

    Das dürfte kein Problem sein - du kannst einen char-Zeiger problemlos in eine konstante std::string-Referenz umwandeln.

    er hat aber einen zeiger auf std::string übergeben 😉



  • queer_boy schrieb:

    er hat aber einen zeiger auf std::string übergeben 😉

    OK, da hatte ich wohl den falschen Code vor Augen - Punkt für dich.



  • Neue Version von to_nueric:

    template<typename T> 
    bool to_numeric(const string& data, T& value) 
    { 
      ostringstream str(data); 
    
      str>>value; 
      return !str;
    }
    

    Vorteil ist dass man die Fehlerbehandlung außerhalb machen kann und man spart sich das angeben des template paramters beim Aufruf.



  • templäd schrieb:

    Neue Version von to_nueric:...
    Vorteil ist dass man die Fehlerbehandlung außerhalb machen kann und man spart sich das angeben des template paramters beim Aufruf.

    Vielleicht geht es nur mir so, aber ich sehe hier auch wieder Nachteile:

    a) Man kann die Funktion nicht in einen anderen Ausdruck "verschachteln" (und gerade bei kleinen Konvertierungsaufrufen mache ich das gerne).
    b) Man kann die Fehlerbehandlung einfach vergessen - und in diesem Fall sehe ich es wirklich als Fehler an (Sprich: Ich würde an dieser Stelle zum Exceptionhandling greifen - und Exceptions lassen sich auch außen behandeln).

    cu André



  • templäd schrieb:

    Neue Version von to_nueric:

    template<typename T> 
    bool to_numeric(const string& data, T& value) 
    { 
      ostringstream str(data); 
    
      str>>value; 
      return !str;
    }
    

    Vorteil ist dass man die Fehlerbehandlung außerhalb machen kann und man spart sich das angeben des template paramters beim Aufruf.

    Ehem... also ich weiß ja nicht. 🙄 Die alte Version fand ich besser. Du hast es verschlimmbessert.

    template<typename T>
    T to_numeric(const string& data)
    {
      ostringstream str(data);
      T val;
      str>>val;
      if(!str)
        throw std::invalid_argument("Value ist ungültig.");
      return val;
    }
    

    So einfach ist das.

    Und sorry, warum eigentlich dieser ganze Aufriss? Noch nie was von boost::lexical_cast gehört?


Anmelden zum Antworten