String in eine Kommazahl konvertieren



  • Hallo,
    wollte frag wie ich einen String (12,3) in eine float Zahl konvertieren kann um sie dann dividieren zu können? Hat jemand ein Quelltextbeispiel?



  • float zahl = boost::lexical_cast<float>("12,3");
    


  • und wenn du kein boost hast:

    std::stringstream s("12.3");
     float f;
     s >> f;
    


  • Artchi schrieb:

    float zahl = boost::lexical_cast<float>("12,3");
    

    .. führt fast immer zu einer boost::bad_lexical_cast-Exception.

    Und wenn tatsächlich eine Komma-Zahl gelesen werden soll, kann man sich so behelfen:

    std::stringstream s("12,3");
        s.imbue( locale("german") ); // Bem.: String "german" ist implementierungsabhängig
        float f;
        s >> f;
    

    Gruß
    Werner



  • Habs nicht ausprobiert. Wenn lexical_cast tatsächlich keine lokalisierten Zahlen versteht, ist das schlecht. Werde das mal überprüfen und notfalls einen Changerequest bei boost reingeben.



  • bei mir kommt der fehler:

    std::stringstream s' has initializer but incomplete type



  • Dann fehlt dir vermutlich die passende Header-Datei:

    #include <sstream>
    


  • alexC++ schrieb:

    std::stringstream s' has initializer but incomplete type

    EDIT: Sollten wir uns verarscht vorkommen?
    http://www.c-plusplus.net/forum/viewtopic-var-p-is-1170909-and-highlight-is-.html#1170909



  • Artchi schrieb:

    Habs nicht ausprobiert. Wenn lexical_cast tatsächlich keine lokalisierten Zahlen versteht, ist das schlecht. Werde das mal überprüfen und notfalls einen Changerequest bei boost reingeben.

    Ne, das wäre ja quatsch. Die Leute sollen das richtige local setzen, wenn sie das Komma da haben wollen. Ich will keine eierlegende Wollmilchsaufunktion, die alles was sich irgendwie mühevoll noch als Zahl interpretieren läßt auch konvertiert.



  • Jester schrieb:

    Artchi schrieb:

    Habs nicht ausprobiert. Wenn lexical_cast tatsächlich keine lokalisierten Zahlen versteht, ist das schlecht. Werde das mal überprüfen und notfalls einen Changerequest bei boost reingeben.

    Ich will keine eierlegende Wollmilchsaufunktion, die alles was sich irgendwie mühevoll noch als Zahl interpretieren läßt auch konvertiert.

    Sehe ich ähnlich. Mich nervt manchmal schon std::stringstream. Für die meisten Fälle ist die Sicherheit (dank eigenem Memory-Management) von std::stringstream ja schick und schön. Für das Umwandeln eines Strings in eine Zahl ist das zusätzliche Kopieren des Strings (hurra, wieder eine Heap-Allokation) aber meistens reine Verschwendung. Nun ist ja auch Verschwendung in der Regel kein Problem, aber da wo es ein Problem ist, ist es schade, dass std::strstream als deprecated eingestuft wurde.
    So muss man am Ende wieder auf alte C-Funktionen zurückgreifen oder aber sich einen eigenen Streambuffer schreiben, der einfach auf einem Array arbeitet. Siehe z.B.: http://fara.cs.uni-potsdam.de/~jsg/array_istream/array_istream.zip



  • Wenn ihr unbedingt lexical_cast<> deutsche Gleitkommazahlen beibringen wollt, könnt ihr über locale::global(locale("german")); ein deutsches Locale für's gesamte Programm festlegen 😉

    @Hume: Erstens hindert dich niemand daran, strstreams zu verwenden (wenn du unbedingt willst). Und zweitens versuchen die auch, sich selber um's Speicher-Managment zu kümmern (wobei die Steuerung nach außen etwas komplizierter ausfällt als bei einem stringstream).



  • CStoll schrieb:

    @Hume: Erstens hindert dich niemand daran, strstreams zu verwenden (wenn du unbedingt willst).

    Äh doch. Der C++ Standard. Was heute als deprecated eingestuft ist, kann beim nächsten Standard entfernt werden. D.h. meine Programme lassen sich 2037 dann vielleicht nicht mehr übersetzen 😮

    Und zweitens versuchen die auch, sich selber um's Speicher-Managment zu kümmern (wobei die Steuerung nach außen etwas komplizierter ausfällt als bei einem stringstream).

    Hast du verstanden, worauf ich hinaus wollte?

    #include <strstream>
    #include <sstream>
    #include <iostream>
    using namespace std;
    int main() {
    	char arr[] = "1.23";
    	char arr2[] = "1.23";
    	istrstream str(arr);
    	arr[0] = '7';
    	double f;
    	str >> f;
    	cout << f << endl;
    
    	istringstream str2(arr2);
    	arr2[0] = '7';
    	str2 >> f;
    	cout << f << endl;
    }
    

    Wird der Unterschied klar? Es ist dabei auch egal, ob man einen C-String oder einen std::string nimmt. istringstream erstellt *immer* eine Kopie.



  • OK, locale::global(locale("german")); habe ich nicht gewusst. Denn wenn ich locale("").name() aufrufem bekomme ich schon german zurück. Aber das ich es global setzen muß, habe ich nicht gewusst. Dann funktioniert also lexical_cast doch problemlos mit deutschen Kommazahlen.



  • lexical_cast ist ja auch nicht viel mehr als:

    template<typename DestType, SourceType>
    DestType lexical_cast(SourceType const& value)
    {
      std::stringstream s;
      s << value;
      DestType result;
      s >> result;
      return result;
    }
    

    Damit verwendet es natürlich alle Einstellungen und Features, die die stream-Bibliothek bietet.


Log in to reply