C-Strings vergleichen



  • Hi,

    ich hab ein Problem mit diesem Programm:

    //Währungsrechner
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    
    using namespace std;
    
    int main()
    {
        double bbetrag, ergebnis;
        char betrag[5], waehrung[6], zielwaehrung[6];
        char USD[] = "USD", EUR[] = "EUR";
        int control1, controll2;
        //int i = 1;
        cout << "****Waehrungsrechner****\n";
        cout << "Umrechnungen fuer USD und EUR \n\n";
        cout << "Bitte Betrag eingeben: ";
        cin >> betrag;
        cout << "\n";
        cout << "Bitte aktuelle Waehrung eingeben: ";
        cin >> waehrung;
        cout << "\n";
        cout << "Bitte Zielwaehrung eingeben: ";
        cin >> zielwaehrung;
        cout << "\n\n";
    
        bbetrag = atof(betrag);
    
        cout << "das Ergebnis wird berechnet." << "\n";
    
        cout << strcmp(waehrung, USD) << " : " << strcmp(zielwaehrung, EUR) << "\n;
    
        if(strcmp(waehrung, USD) == 0)
        {
                    ergebnis = bbetrag * 1.3912;
                    cout << bbetrag << " " << waehrung << " ist " << ergebnis << " " << zielwaehrung;
        }
        if(strcmp(zielwaehrung, EUR) == 0)
        {
                    ergebnis = bbetrag * 0.7188;
                    cout  << bbetrag << " " << waehrung << " ist " << ergebnis << " " << zielwaehrung;
        }
    
     return 0;
    }
    

    und zwar soll diese Programm Dollar in Euro und umgekehrt umrechnen.
    Mein Problem ist, dass er die C-Strings nicht richtig vergleicht. Zum gucken wie er sie vergleicht hab ich diese Zeile eingefügt:

    cout << strcmp(waehrung, USD) << " : " << strcmp(zielwaehrung, EUR);
    

    die Ausgaben bei verschiedenen Eingaben sind folgende:

    ****Waehrungsrechner****
    Umrechnungen fuer USD und EUR
    
    Bitte Betrag eingeben: 500
    
    Bitte aktuelle Waehrung eingeben: EUR
    
    Bitte Zielwaehrung eingeben: USD
    
    das Ergebnis wird berechnet.
    -1 : 1
    
    ****Waehrungsrechner****
    Umrechnungen fuer USD und EUR
    
    Bitte Betrag eingeben: 500
    
    Bitte aktuelle Waehrung eingeben: USD
    
    Bitte Zielwaehrung eingeben: EUR
    
    das Ergebnis wird berechnet.
    0 : 0
    500 USD ist 695.6 EUR500 USD ist 359.4 EUR
    

    kann mir da jemand helfen, dass diese Ausgabe o. ä. kommt:

    ****Waehrungsrechner****
    Umrechnungen fuer USD und EUR
    
    Bitte Betrag eingeben: 500
    
    Bitte aktuelle Waehrung eingeben: USD
    
    Bitte Zielwaehrung eingeben: EUR
    
    das Ergebnis wird berechnet.
    0 : -1
    500 USD ist 359.4 EUR
    

    schon mal vielen dank für antworten 🙂

    HKEY



  • huhu,

    ich verstehe gerade iwie nicht genau, wo nun genau das Problem liegt.
    Was mir nur grad auffällt, dass beide IFs genau das gleiche machen bis auf die Multiplikation, ist das so gewollt?



  • Nimm einfach std::string und du musst nicht so hässlichen Code schreiben.

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int main()
    {
    	double betrag;
    	std::string waehrung;
    	std::string zielwaehrung;
    
    	std::cout << "Bitte Betrag eingeben: "; 
    	std::cin >> betrag;
    
    	std::cout << "Bitte aktuelle Waehrung eingeben: "; 
    	std::cin >> waehrung;
    
    	std::cout << "Bitte Zielwaehrung eingeben: ";
    	std::cin >> zielwaehrung;
    
    	double ergebnis = 0;
    
    	if (waehrung == "USD")
    	{
    		ergebnis = betrag * 1.3912;
    	}
    
    	if (waehrung == "EUR")
    	{
    		ergebnis = betrag * 0.7188;
    	}
    
    	cout << betrag << " " << waehrung << " ist " << ergebnis << " " << zielwaehrung << std::endl;
    
    	return 0;
    }
    


  • danke für die antworten

    @Dweb
    nein, das wahr nicht beabsichtigt.

    @,,,,
    bei strings bin ich in meinem Buch noch nich werde es mir aber jetzt angucken.

    hab jetzt auch noch mal auf den Quelltext geguckt und da ist mir der Fehler direkt aufgefallen. Irgendwie bin ich schon doof 🙂
    Hier die richtige Lösung:

    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    
    using namespace std;
    
    int main()
    {
        double bbetrag, ergebnis;
        char betrag[5], waehrung[6], zielwaehrung[6];
        char USD[] = "USD", EUR[] = "EUR";
        int control1, controll2;
        cout << "****Waehrungsrechner****\n";
        cout << "Umrechnungen fuer USD und EUR \n\n";
        cout << "Bitte Betrag eingeben: ";
        cin >> betrag;
        cout << "\n";
        cout << "Bitte aktuelle Waehrung eingeben: ";
        cin >> waehrung;
        cout << "\n";
        cout << "Bitte Zielwaehrung eingeben: ";
        cin >> zielwaehrung;
        cout << "\n\n";
    
        bbetrag = atof(betrag);
    
        cout << "das Ergebnis wird berechnet." << "\n";
    
        cout << strcmp(waehrung, USD) << " : " << strcmp(waehrung, EUR) << "\n";
    
        if(strcmp(waehrung, USD) == 0)
        {
                    ergebnis = bbetrag * 0.7188;
                    cout << bbetrag << " " << waehrung << " ist " << ergebnis << " " << zielwaehrung;
        }
        if(strcmp(waehrung, EUR) == 0)
        {
                    ergebnis = bbetrag * 1.3912;
                    cout  << bbetrag << " " << waehrung << " ist " << ergebnis << " " << zielwaehrung;
        }
    
        return 0;
    }
    

  • Mod

    HKEY schrieb:

    bei strings bin ich in meinem Buch noch nich werde es mir aber jetzt angucken.

    string ist in deinem Buch noch nicht drangekommen, dafür aber char-Arrays, atof und strcmp? Das Buch vermittelt anscheinend auch einen sehr ungwöhnlichen Stil. Das Deklarieren aller Variablen am Programmanfang ist beispielsweise hochgradig ungewöhnlich. Außerdem ist alles merkwürdig imperativ für C++.

    Mit meinen Psychokräften kann ich sogar spüren, wer der Autor deines Buches ist. Hat er die Initialen J.W.?

    Etwas vom Thema ab: Wir haben auch brandaktuell eine Diskussion, warum double eher nicht für das Rechnen mit Geld geeignet ist:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-276166



  • SeppJ schrieb:

    Mit meinen Psychokräften kann ich sogar spüren, wer der Autor deines Buches ist. Hat er die Initialen J.W.?

    deine Psychokräfte haben dir das richtige gesagt. Es ist das buch "C++ von A bis Z".

    SeppJ schrieb:

    Etwas vom Thema ab: Wir haben auch brandaktuell eine Diskussion, warum double eher nicht für das Rechnen mit Geld geeignet ist:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-276166

    womit soll ich denn sonst rechnen?



  • SeppJ schrieb:

    HKEY schrieb:

    bei strings bin ich in meinem Buch noch nich werde es mir aber jetzt angucken.

    string ist in deinem Buch noch nicht drangekommen, dafür aber char-Arrays, atof und strcmp? Das Buch vermittelt anscheinend auch einen sehr ungwöhnlichen Stil. Das Deklarieren aller Variablen am Programmanfang ist beispielsweise hochgradig ungewöhnlich. Außerdem ist alles merkwürdig imperativ für C++.

    Mit meinen Psychokräften kann ich sogar spüren, wer der Autor deines Buches ist. Hat er die Initialen J.W.?

    Etwas vom Thema ab: Wir haben auch brandaktuell eine Diskussion, warum double eher nicht für das Rechnen mit Geld geeignet ist:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-276166

    Das Buch von J.W lese ich auch. Strings kommen dort erst später dran, da er in dem Kapitel direkt auf die gesamte Klasse eingeht. Strcmp ist wohl logisch dass man die nahe von Arrays bzw. C-Strings beigebracht bekommt. atof wird im Buch nicht erwähnt, muss der TE wohl selber recherchiert haben.
    Generell gibt es an dem Buch nichts auszusetzten, oder sehe ich das falsch ?
    Sorry, dass das OT ist, aber das hat mich an dieser Stelle interessiert.


  • Mod

    HKEY schrieb:

    deine Psychokräfte haben dir das richtige gesagt. Es ist das buch "C++ von A bis Z".

    Wie du dir nun sicher denken kannst, war mein Kommentar auch eine verkappte Warnung davor, das Buch weiter zu benutzen.

    SeppJ schrieb:

    Etwas vom Thema ab: Wir haben auch brandaktuell eine Diskussion, warum double eher nicht für das Rechnen mit Geld geeignet ist:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-276166

    womit soll ich denn sonst rechnen?

    Normalerweise mit einer hübschen kleinen Geldklasse die alles automatisch managed. Da Herr Wolff aber nicht viel von so "modernem Schnickschack" wie Klassen oder gar Objektorientierung zu halten scheint 🙄 , sagt dir dies vermutlich nichts. Eine simple aber gute Ausweichlösung ist es, einen Integer zu nehmen und in Cent zu denken.



  • Felixxx schrieb:

    Generell gibt es an dem Buch nichts auszusetzten, oder sehe ich das falsch ?

    Also hier im Forum sind wir anscheinend über die Entrüstung schon hinaus und spotten nur noch, siehe SeppJ. Das mit den Psychokräften war wirklich lustig. Er hat das Buch nämlich nicht gelesen und hat auch nicht das Währungsbeispiel gekannt, aber der erschreckend häßliche Stil läßt einen sofort daran denken.
    Und siehe da, wenn ein Codebeispiel nur häßlich genug ist, wird's schon von J.W. kommen.



  • Geldbeträge sind meistens am sinnvollsten in Cent mit großen Integertypen berechnet (etwa std::tr1::int64_t). Es kommt ja eher selten vor, dass man Geldbeträge miteinander multipliziert - 10€ * 10€ = 100€², und mir fällt gerade kein guter Verwendungszweck für €² ein. Gelegentlich macht es trotzdem Sinn, Fließkommazahlen zu verwenden (hauptsächlich, wenn man die Eingabedaten eh als doubles kriegt und nachher wieder in doubles stopfen muss), allerdings sollte man dann darauf achten, dass immer sofort auf zwei Stellen gerundet wird und sicher sein, dass kleinere Abweichungen (praktisch heißt das um die Größenordnung 1e-14) kein Problem darstellen - 0,01 kann binär nicht exakt dargestellt werden!

    In einem Excel-Plugin hat mir Folgendes gute Dienste geleistet:

    class money_amount {
    public:
      inline money_amount() : val_(0.0) {}
      inline money_amount(double val)
        : val_(std::floor(val * 100.0 + 0.5) / 100.0) {}
    
      inline money_amount &operator=(money_amount const &other) {
        val_ = other.val_;
        return *this;
      }
    
      inline double get() const { return val_; }
      inline operator double() const { return get(); }
    
    private:
      double val_;
    };
    

    Das ist natürlich ziemlich rudimentär, sollte aber für viele Anwendungsfälle völlig ausreichen.

    Was Jürgen Wolf angeht, der ist hier schon ziemlich berüchtigt. Seine Bücher enthalten böse Anfängerfehler und Fehlinformationen; er schreibt seinen Code und seine Bücher wie ein Web-Designer (d.h. nach dem Motto "wenn's bei mir geht, wird's schon richtig sein), welche dementsprechend ohne Ende undefiniertes Verhalten enthalten und propagieren. Beispielsweise hat er von Sequenzpunkten scheinbar nie etwas gehört und erzählt, dass Parameterauswertung bei Funktionsaufrufen von rechts nach links passiert (dieses Verhalten ist im Standard nicht definiert).

    Bei C++ sieht es noch schlimmer aus; er kennt und beschreibt bestenfalls C mit Klassen und kann dem nicht mal richtiges C zugrunde legen. Tut euch selbst einen Gefallen und meidet seine Werke; er versteht die Sprachen nicht wesentlich besser als ihr.



  • Inwiefern sollte J.W. nichts von OOP halten ? Das verstehe ich nicht, er schreibt immer wieder davon, erklärt die Prinzipien, erklärt wozu es dient, und ist glaube ich 100 oder mehr Seiten lang auf Klassen eingegangen. Redet ihr evtl. von alten Ausgaben ?



  • //Währungsrechner
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    
    using namespace std;
    
    int main()
    {
        double bbetrag, ergebnis;//Zu früh definiert. 
        //"Mache Variablen so lokal wie möglich" wäre C++. 
        //Das hier ist C. Man lernt hier also veralteten Stil. 
        char betrag[5], waehrung[6], zielwaehrung[6];//Die Größen sind recht knapp. Und 
        //für sowas nimmt man wirklich nur std::string. Also einfach ein schlechtes 
        //Beispiel. Außerdem wieder zu früh definiert. 
        char USD[] = "USD", EUR[] = "EUR";//Erstens, warum fehlt das const? Zweitens WOZU???
        int control1, controll2;//Nicht benutzt.
        //int i = 1;
        cout << "****Waehrungsrechner****\n";
        cout << "Umrechnungen fuer USD und EUR \n\n";
        cout << "Bitte Betrag eingeben: ";
        cin >> betrag;
        cout << "\n";
        cout << "Bitte aktuelle Waehrung eingeben: ";
        cin >> waehrung;
        cout << "\n";
        cout << "Bitte Zielwaehrung eingeben: ";
        cin >> zielwaehrung;
        cout << "\n\n";
    
        bbetrag = atof(betrag);//Ähm, bbetrag, um's von betrag zu unterscheiden?
        //atof sieht man auch nur in C. Wieder schlechtes Beispiel. Warum nicht 
        //gleich einen double einlesen? 
    
        cout << "das Ergebnis wird berechnet." << "\n";//Warum hier den Umbruch 
        //drangehängt, während oben drin?
    
        cout << strcmp(waehrung, USD) << " : " << strcmp(zielwaehrung, EUR) << "\n";//OK, 
        //Debugausgabe halt. 
    
        if(strcmp(waehrung, USD) == 0)//Was ist an USD besser als an "USD"?
        {
            ergebnis = bbetrag * 1.3912;
            cout << bbetrag << " " << waehrung << " ist " << ergebnis << " " << zielwaehrung;//A
        }
        if(strcmp(zielwaehrung, EUR) == 0)
        {
            ergebnis = bbetrag * 0.7188;
            cout  << bbetrag << " " << waehrung << " ist " << ergebnis << " " << zielwaehrung;//B
        }
        //Hier gehören A und B hin. Man schreibt nicht ohne Not zwei völlig identische Zeilen. 
    
        return 0;
    }
    


  • volkard schrieb:

    //Währungsrechner
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    
    using namespace std;
    
    int main()
    {
        double bbetrag, ergebnis;//Zu früh definiert. 
        //"Mache Variablen so lokal wie möglich" wäre C++. 
        //Das hier ist C. Man lernt hier also veralteten Stil.
        //-> Ich weiß nich, was am alten C Stil auszusetzen ist,
        //-> ist immerhin ein sehr sauberer Stil.  
        char betrag[5], waehrung[6], zielwaehrung[6];//Die Größen sind recht knapp. Und 
        //für sowas nimmt man wirklich nur std::string. Also einfach ein schlechtes 
        //Beispiel. Außerdem wieder zu früh definiert.
        //-> Ob std::string oder c-Arrays ist wohl Geschmackssache
        //-> Die recht knappen Größen stammen vom TE und sind zwecksgemäß
        //-> gewählt, nehme ich mal an  
        char USD[] = "USD", EUR[] = "EUR";//Erstens, warum fehlt das const? Zweitens WOZU???
        //-> Das macht natürlich wirklich wenig Sinn, aber so hat es 
        //-> J.W. auch nicht gemacht, stammt vom TE  
        int control1, controll2;//Nicht benutzt. -> Stammt vom TE
        //int i = 1;
        cout << "****Waehrungsrechner****\n";
        cout << "Umrechnungen fuer USD und EUR \n\n";
        cout << "Bitte Betrag eingeben: ";
        cin >> betrag;
        cout << "\n";
        cout << "Bitte aktuelle Waehrung eingeben: ";
        cin >> waehrung;
        cout << "\n";
        cout << "Bitte Zielwaehrung eingeben: ";
        cin >> zielwaehrung;
        cout << "\n\n";
    
        bbetrag = atof(betrag);//Ähm, bbetrag, um's von betrag zu unterscheiden?
        //atof sieht man auch nur in C. Wieder schlechtes Beispiel. Warum nicht 
        //gleich einen double einlesen? 
        // -> Stammt ebenfalls vom TE, atof wird im C++Buch nie erwähnt
        
    
        cout << "das Ergebnis wird berechnet." << "\n";//Warum hier den Umbruch 
        //drangehängt, während oben drin?
        //-> TE
        cout << strcmp(waehrung, USD) << " : " << strcmp(zielwaehrung, EUR) << "\n";//OK, 
        //Debugausgabe halt. 
    
        if(strcmp(waehrung, USD) == 0)//Was ist an USD besser als an "USD"? -> TE
        {
            ergebnis = bbetrag * 1.3912;
            cout << bbetrag << " " << waehrung << " ist " << ergebnis << " " << zielwaehrung;//A
        }
        if(strcmp(zielwaehrung, EUR) == 0)
        {
            ergebnis = bbetrag * 0.7188;
            cout  << bbetrag << " " << waehrung << " ist " << ergebnis << " " << zielwaehrung;//B
        }
        //Hier gehören A und B hin. Man schreibt nicht ohne Not zwei völlig identische Zeilen. 
        //-> Das stimmt natürlich richtig, sind aber zwecksgemäß einfach gehaltene
        //-> Beispielcodes für den Anfang, später vermeidet er sowas. 
        return 0;
    }
    


  • Also gut, ich hab mal etwas in der Jauchegrube nach Brocken gefischt. Ein paar

    ~Edit vom gemeinen Volkard: konkrete Fehlermeldungen weggemacht und nur die Anzahl gelassen.
    ~

    C von A-Z
    Fehler: 5

    Grundkurs C
    Fehler: 1

    "C++ von A bis Z" ist voll mit Syntaxfehlern. In der Leseprobe gibt es kein Codebeispiel mit Klassen, das ein Compiler akzeptieren würde (fehlende Semikola). Die für ein Lehrbuch notwendige Sorgfältigkeit lässt dies vermissen. Ferner kann ich über die Absätze zu Casts nur den Kopf schütteln; was hier eigentlich passiert, scheint dem Autor völlig unbekannt zu sein. Ich wette einiges, dass er über die Ausgabe von

    #include <iostream>
    
    struct A {
      A() { }
      A(A const &) { std::cout << "A(A const &)" << std::endl; }
    };
    struct B : A { };
    
    int main() {
      B b;
      static_cast<A>(b);
    }
    

    höchst erstaunt wäre.

    Diese Bücher sind mit Halbwissen und Raterei zusammengeschlampt und nicht dazu geeignet, irgendjemandem irgendetwas beizubringen. Es macht auf mich den Eindruck, als habe das nicht mal jemand korrekturgelesen.



  • Felixxx schrieb:

    //-> Ich weiß nich, was am alten C Stil auszusetzen ist,
    //-> ist immerhin ein sehr sauberer Stil.

    Der Stil muß doch zur Sprache passen. In einem C++-Programm hat das nichts zu suchen. Wäre das ein C-Programm, mit scanf/printf statt cin/cout wäre alles in Ordnung. Ich fürchte, es war mal ein C-Programm, es war einfach mal ein C-Buch und wurde in einer Nacht-Und-Nebel-Aktion um ein paar Kapitel C++ erweitert und Programme wurden in Richtung C++ oberflächlich angestrichen, wobei so ein Pseudo-C-- rauskommt. Ein C-Programm mit cin und cout.
    Du bist nicht zufällig dieser J.W. selber?



  • seldon schrieb:

    Also gut, ich hab mal etwas in der Jauchegrube nach Brocken gefischt. Ein paar Beispiele:

    Nicht zu viel Fehler konkret nennen.
    Er soll uns nicht provozieren, daß wir ihm kostenlos sein Buch reparieren.
    Er kann soll jemanden zu einem angemessenen Stundensatz buchen.
    (Ich würde das Posting an Deiner Stelle sogar deswegen wieder rausnehmen.)



  • @ Seldon :
    Gut, das C-Buch habe ich nie gelesen, also kann ich das schlecht navollziehen.
    Ich bin mir aber sicher, dass es in fast jedem Buch Fehler gibt.
    Ich weiß nicht welche Fassung du von dem C++ Buch gelesen hast, aber die kostenpflichtige ist vollkommen richtig, also vom Syntax her.

    @ volkard : Dass der Stil zur Sprache passen sollte stimmt natürlich auf der einen Seite, auf der anderen Seite warum sollte man Gutes weg/verwerfen?



  • Felixxx schrieb:

    Ich weiß nicht welche Fassung du von dem C++ Buch gelesen hast, aber die kostenpflichtige ist vollkommen richtig, also vom Syntax her.

    Behauptung zur Kenntnis genommen und schlicht nicht geglaubt. Und ich werde es nicht kostenlos reparieren, ätsch.



  • volkard schrieb:

    Nicht zu viel Fehler konkret nennen.
    Er soll uns nicht provozieren, daß wir ihm kostenlos sein Buch reparieren.
    Er kann soll jemanden zu einem angemessenen Stundensatz buchen.
    (Ich würde das Posting an Deiner Stelle sogar deswegen wieder rausnehmen.)

    Kann ich nicht; unregistriert. Du als Moderator kannst es aber meinetwegen mit einer entsprechenden Notiz ersetzen.

    Ansonsten werde ich einen Teufel tun und für diesen Schund Geld zum Fenster rauswerfen. Syntaxfehler hin oder her, Jürgen Wolf hat weder von C noch von C++ genug verstanden, um Bücher darüber zu schreiben. Wenn er ein paar Jahre damit verbringt, Programmierung tatsächlich zu lernen, können wir vielleicht noch mal darüber reden, aber bis dahin sehe ich ihn als ein Musterbeispiel des Dunning-Kruger-Effekts.



  • Naja, es ist halt einfach Fakt. Es fehlt kein einziges Semikolon.
    Es hat keiner von Dir verlangt irgendwas zu reparieren; man kann ja auch nichts reparieren, was nicht kaputt ist, nicht wahr ? 🙂


Anmelden zum Antworten