Zahlen richtig wiedergeben



  • Hallo ich bin gerade dabei mich in die hohe Kunst der C++ Programmierung einzuarbeiten 🙂

    Es wurde hier die Aufgabenstellung genannt:
    Entwickeln Sie eine C++-Anwendung, die den Anwender zur Eingabe einer vierstelligen Zahl auffordert. Das Programm soll daraufhin die Quersumme der vierstelligen Zahl errechnen und das Ergebnis auf den Bildschirm ausgeben

    Nun erst mal mein Programmcode dazu:

    #include <iostream>
    
    using namespace std;
    int main()
    
    {
        char zahl[4],Quersumme; //Variablendeklinaration
        cout<<" Bitte geben sie eine Vierstellige Zahl ein."<<endl;
        cin>> zahl;
        Quersumme=zahl[0]+zahl[1]+zahl[2]+zahl[3];
        cout<<" Die Zahl ist " <<zahl<<" und deren Quersumme beträgt " <<Quersumme<<"."<<endl;
        system("Pause");
    }
    

    nun kommt allerdings bei der Quersumme ein Zeichen raus ╩.
    Wollte fragen wie ich das beheben kann
    Danke schon mal


  • Mod

    Du hast drei Fehler:
    1. Ein char-Array für 4 Zeichen muss Größe 5 haben, ansonsten schreibt cin am Ende die Nullterminierung wer weiß wohin.
    2. Der Zahlenwert den Zeichens '0' ist nicht 0. Was genau der Wert ist, ist nicht definiert, auf den meisten Systemen ist es 48. Schönerweise ist aber zumindest festgelegt, dass der Wert von '1' genau um 1 größer ist als der Wert von '0' und so weiter. Daher kannst du um aus dem Zeichen '0' den Wert 0 und aus dem Zeichen '1' den Wert 1 und so weiter zu bekommen einfach dies machen: zeichen - '0'
    Ist dann auch absolut plattformunabhängig.
    3. Die Quersumme kann man zwar als char nehmen (da sie maximal 4*9=36<255 ist), aber es bietet sich eher ein int an. Denn dann wird bei der Ausgabe auch gleich ein dezimaler-Zahlenwert ausgegeben. Wenn du einen char als Quersumme hast, würde dieser bei der Ausgabe als das entsprechende Zeichen aus der Zeichentabelle wiedergegeben, sofern du ihn vor der Ausgabe nicht in einen int (oder einen anderen Zahlentyp) castest.



  • Woher weißt du, ob 4 Stellen eingegeben wurden und nicht mehr oder weniger?



  • SeppJ schrieb:

    Du hast drei Fehler:
    1. Ein char-Array für 4 Zeichen muss Größe 5 haben, ansonsten schreibt cin am Ende die Nullterminierung wer weiß wohin.
    2. Der Zahlenwert den Zeichens '0' ist nicht 0. Was genau der Wert ist, ist nicht definiert, auf den meisten Systemen ist es 48. Schönerweise ist aber zumindest festgelegt, dass der Wert von '1' genau um 1 größer ist als der Wert von '0' und so weiter. Daher kannst du um aus dem Zeichen '0' den Wert 0 und aus dem Zeichen '1' den Wert 1 und so weiter zu bekommen einfach dies machen: zeichen - '0'
    Ist dann auch absolut plattformunabhängig.
    3. Die Quersumme kann man zwar als char nehmen (da sie maximal 4*9=36<255 ist), aber es bietet sich eher ein int an. Denn dann wird bei der Ausgabe auch gleich ein dezimaler-Zahlenwert ausgegeben. Wenn du einen char als Quersumme hast, würde dieser bei der Ausgabe als das entsprechende Zeichen aus der Zeichentabelle wiedergegeben, sofern du ihn vor der Ausgabe nicht in einen int (oder einen anderen Zahlentyp) castest.

    also ich ging davon aus wenn ich jetzt in das array vier Zahlen eingebe zb 1234
    wäre
    zahl[0]=1
    zahl[1]=2
    zahl[2]=3
    zahl[3]=4
    ist das soweit richtig?

    Wenn ich den Typ char durch int ersetzte kommt bei mir in der eingabe Zeile ein Fehler.
    Ich nehme an das kommt von int zahl[4] und cin>> zahl. Das funktioniert so nur bei char

    Danke abermals 🙂



  • hiho, nein 😉

    wenn du in ein char-array 1234 eingibst sieht das danach so aus:

    zahl[0]='1'
    zahl[1]='2'
    zahl[2]='3'
    zahl[3]='4'
    zahl[4]='\0' // Terminierungszeichen nicht vergessen
    


  • Schau dir mal Strings in C/C++ an. char[] is eher für C, die C++-Strings bieten schon etwas mehr Kompfort. Vor allem aber solltest du wissen, wie die funktionieren!



  • Ja, da war ich leider noch nicht. Ist in dem Tutorial andscheindend schlecht geordnet 😉



  • Jonas.M schrieb:

    Ich nehme an das kommt von int zahl[4] und cin>> zahl. Das funktioniert so nur bei char

    Schreib int zahl; statt int zahl[4], dann passt das auch. Denn du willst ja nur eine Zahl einlesen und nicht vier.



  • Michael E. schrieb:

    Jonas.M schrieb:

    Ich nehme an das kommt von int zahl[4] und cin>> zahl. Das funktioniert so nur bei char

    Schreib int zahl; statt int zahl[4], dann passt das auch. Denn du willst ja nur eine Zahl einlesen und nicht vier.

    Naja im konkreten Fall (Quersumme bilden) finde ich es günstiger, einen String einzulesen. Da erspart man sich elegant irgendwelches Rechengefrickel.



  • Die char[]-Variante geht nur leider vollständig an der Realität vorbei.

    Wenn ich eine Zahl als Input haben will, lese ich eine Zahl ein und nichts, in dem vielleicht eine Zahl stehen könnte, wenn mir der User den Gefallen tut und eine positive ganze Zahl mit genau vier Ziffern ohne Vorzeichen und sonstigem Pipapo liefert und ich das nichtmal überprüfe. Übrigens kann ich mir gut vorstellen, dass das "Rechengefrickel" die eigentliche Aufgabe ist. Meiner Meinung nach ist das auch der Teil, bei dem der Fragesteller am meisten lernt und überhaupt nicht schwer. Doch wenn er es geschafft hat, hat er ein erstes Gefühl, wie man zu einer Aufgabenstellung einen Algorithmus entwirft und diesen implementiert.

    Edit: Ach ja, Variablen werden nicht dekliniert. Da war wohl einer zu viel im Lateinunterricht 😉



  • Wenn die Aufgabe heißt "geben Sie die Quersumme einer vom User eingegebenen Zahl aus" und man liefert etwas alá

    int main()
    {
        std::string zahl;
        cin >> zahl;
        int quersumme = 0;
        for(int i = 0; i < zahl.size(); ++i)
            quersumme += zahl[i] - '0';
        cout << quersumme << endl;
    }
    

    finde ich das eine sehr elegante Lösung. Und warum sollte man sich auch die Arbeit machen, den eingelesenen Ziffernstrom erst in einen int und dann wieder zurück in einen Ziffernstrom zu verwandeln?



  • mhm schreibfehler 😛
    deklarieren war gemeint 😉

    ja die lösung mit der for kommt erst in der nächsten Aufgabe 😛

    und nochmal eine Lösung zur ersten Aufgabe...

    #include <iostream>
    #include <string>
    using namespace std;
    
    int main()
    
    {
          string zahl,Quersumme;
          cin>> zahl;
          Quersumme=zahl[0]+zahl[1]+zahl[2]+zahl[3];
          cout<<"Die Zahl lautet "<<zahl[0]<<zahl[1]<<zahl[2]<<zahl[3]<<"und deren Quersumme lautet " << Quersumme<< endl;
          system("Pause");
    
    }
    

    wieder das misteriöse zeichen ^^



  • ipsec schrieb:

    finde ich das eine sehr elegante Lösung.

    Ich nicht.

    Und warum sollte man sich auch die Arbeit machen, den eingelesenen Ziffernstrom erst in einen int und dann wieder zurück in einen Ziffernstrom zu verwandeln?

    LOL, damit hast du ja mal überhaupt nichts zu tun.

    cin >> zahl;
    cout << zahl;
    

    Das ist exakt derselbe Code, egal, ob zahl ein int oder ein string oder was auch immer ist.

    Andersrum kann ich genauso fragen: Warum sollte man sich die Mühe machen und von ASCII-Zeichen in Zahlen umrechnen? Du siehst ja, welche Probleme der OP damit hat.



  • Aber vor der Verwendung eines char[]-Strings sollte doch wenigstens erleutert werden, dass diese mit einem '\0' abgeschlossen werden und daher ein Zeichen mehr brauchen.
    Hin oder her, im Prinzip ist das schon recht elegant, anstatt for kannst du auch while nehmen oder du schreibst es halt [0]+[1]+[2]+[3], zum üben Jacke wie Hose.
    Da das Tutorial offensichtlich noch nicht einmal bei for angekommen ist, wirst du dir wohl auch über die Validierung der Eingabe keine Gedanken machen müssen. Weil weder die Anzahl noch die Art (Zahl oder Buchstabe) der eingegebenen Zeichen wird überprüft. Das könnte recht Fehleranfällig werden...
    Übrigens die Eingabe als int bzw. uint hätte schon dem Charme, dass eben dieses dann ganz einfach wird bzw. entfällt. Und es gibt ja auch sowas wie inttostr (oder so ähnlich), aber ob das schon vor for dran war...



  • Heimelchen schrieb:

    Übrigens die Eingabe als int bzw. uint hätte schon dem Charme, dass eben dieses dann ganz einfach wird bzw. entfällt.

    Eben, die Validierung wird einem geschenkt.

    Und es gibt ja auch sowas wie inttostr (oder so ähnlich), aber ob das schon vor for dran war...

    Das braucht man doch gar nicht.



  • Michael E. schrieb:

    Und warum sollte man sich auch die Arbeit machen, den eingelesenen Ziffernstrom erst in einen int und dann wieder zurück in einen Ziffernstrom zu verwandeln?

    LOL, damit hast du ja mal überhaupt nichts zu tun.

    Doch durchaus. Die Umwandlung Ziffernstrom -> Zahl macht natürlich cin , aber es wird eben gemacht. Und es ist sinnlos, wenn man danach die Zahl nur wieder in einzelne Ziffern zerlegt.
    Außerdem wüsste ich nicht, was an

    int main()
    {
        int zahl, quersumme = 0;
        cin >> zahl;
        while(zahl > 0)
        {
            quersumme += zahl % 10;
            zahl /= 10;
        }
        cout << quersumme << endl;
    }
    

    eleganter sein sollte, ganz davon abgesehen, dass es unperformanter ist.

    Die Eingabevalidierung muss ich natürlich bei der string-Variante selber machen, muss ich aber sonst auch, spätestens wenn der User auf die Idee kommen könnte, 123.456 mit Erwartung des korrekten Ergebnisses einzugeben.



  • Michael E. schrieb:

    Heimelchen schrieb:

    Übrigens die Eingabe als int bzw. uint hätte schon dem Charme, dass eben dieses dann ganz einfach wird bzw. entfällt.

    Eben, die Validierung wird einem geschenkt.

    Und es gibt ja auch sowas wie inttostr (oder so ähnlich), aber ob das schon vor for dran war...

    Das braucht man doch gar nicht.

    Ahja? Gibts ne Quersummenfunktion? Oder möchtest du dir jede Stelle "Rausdividieren"? Dann ist es wohl eher Geschmackssache, was eleganter ist. Von der Performance her wird beides ähnlich sein...



  • ipsec schrieb:

    Michael E. schrieb:

    Und warum sollte man sich auch die Arbeit machen, den eingelesenen Ziffernstrom erst in einen int und dann wieder zurück in einen Ziffernstrom zu verwandeln?

    LOL, damit hast du ja mal überhaupt nichts zu tun.

    Doch durchaus. Die Umwandlung Ziffernstrom -> Zahl macht natürlich cin

    Wie kann man sich in so kurzer Zeit selbst widersprechen?

    aber es wird eben gemacht.

    Na und?

    Außerdem wüsste ich nicht, was an [...] eleganter sein sollte

    Es wird auf Zahlen operiert. Außerdem Lerneffekt blabla => kannst du oben nachlesen.

    ganz davon abgesehen, dass es unperformanter ist.

    Erstens: Beweisen. Zweitens: Na und?

    Die Eingabevalidierung muss ich natürlich bei der string-Variante selber machen, muss ich aber sonst auch, spätestens wenn der User auf die Idee kommen könnte, 123.456 mit Erwartung des korrekten Ergebnisses einzugeben.

    Bullshit. Quersummen sind nur auf natürlichen Zahlen definiert.



  • Michael E. schrieb:

    ipsec schrieb:

    Michael E. schrieb:

    Und warum sollte man sich auch die Arbeit machen, den eingelesenen Ziffernstrom erst in einen int und dann wieder zurück in einen Ziffernstrom zu verwandeln?

    LOL, damit hast du ja mal überhaupt nichts zu tun.

    Doch durchaus. Die Umwandlung Ziffernstrom -> Zahl macht natürlich cin

    Wie kann man sich in so kurzer Zeit selbst widersprechen?

    Der User gibt ein: '1' '2' '3' '4', cin macht daraus 1234. Danach macht man aus 1234 wieder 1 2 3 4 um die Quersumme zu bilden. Das kann man sich sparen bzw. dahin kommt man leichter.

    Michael E. schrieb:

    aber es wird eben gemacht.

    Na und?

    Performance? Unnötiger Aufwand? Da fällt dir sicher was ein.

    Michael E. schrieb:

    Außerdem wüsste ich nicht, was an [...] eleganter sein sollte

    Es wird auf Zahlen operiert. Außerdem Lerneffekt blabla => kannst du oben nachlesen.

    Der TE lernt C++ und nicht Algebra. Warum sollte man eine Quersumme immer mit Mitteln der Mathematik ermitteln, wenn es ausgehend von der Darstellungsform viel effizientere Möglichkeiten gibt?

    Michael E. schrieb:

    ganz davon abgesehen, dass es unperformanter ist.

    Erstens: Beweisen. Zweitens: Na und?

    Hab jetzt leider keinen Compiler, aber sowohl Einlesen einer Zahl, als auch Modulo und Division sind relativ teure Operationen im Vergleich zum simplen Subtrahieren und Addieren. Und mit der "na und?"-Einstellung kommst du wohl nicht weit. Sicher kann man es mit der Optimierung übertreiben, aber bei nicht eingeschränkter Lesbarkeit sollte man doch die performantere Variante wählen. Ich nehme auch nicht vector , wenn ich set will, weil ich mir sage "Na und? Ob ich mit O(n) oder O(log n) suche, ist doch egal".

    Michael E. schrieb:

    Die Eingabevalidierung muss ich natürlich bei der string-Variante selber machen, muss ich aber sonst auch, spätestens wenn der User auf die Idee kommen könnte, 123.456 mit Erwartung des korrekten Ergebnisses einzugeben.

    Bullshit. Quersummen sind nur auf natürlichen Zahlen definiert.

    Richtig. Dem in diesem Fakt unwissenden User ist aber mit 6 als Ausgabe (weil cin beim ersten Nicht-Ziffern-Zeichen aufhört, wenn ich mich jetzt richtig erinnere) ebenso wenig geholfen wie mit 21+'.'-'0' (was auch immer das jetzt ist). Also brauch man in beiden Fällen eine Validierung, die über die von cin hinausgeht.



  • Jaja, erzählst mir hier einen von Performance-Mikro-Nano-Optimierungen und benutzt std::string 🙄

    Na wenn du meinst, dass ich mit meiner Einstellung nicht weit komme, dann bleib halt bei deiner Meinung. Ich weiß auf jeden Fall, was absolut tödlich für Anfänger ist: vorzeitige Optimierung.


Anmelden zum Antworten