Anfänger - Römische Zahlen ausgeben



  • Heyho,
    Als Teil meines Studiums habe ich seit diesem Semester auch Informatik -> C/C++

    Da ich aber keine Lust habe auf die Übungen zu warten und momentan Zeit und Lust zum Programmieren arbeite ich momentan ein wenig vor. War bis jetzt auch kein Problem, da ziemlich einfach. Nur jetzt hänge ich an einem Programm und weiß nicht wieso es nicht das tut was es tun soll:

    using namespace std;
    
    int main(int argc, char *argv[])
    {char eingabe;
    
    /* Eingabe */
    cout<<endl;
    cout<<"Bitte roemische Zahl eingeben: ";
                 cin>>eingabe;
    
    system("cls");
    
    /*Umwandlung*/
    
    if(eingabe=='M'||'D'||'C'||'L'||'X'||'V'||'I')
    {
    switch(eingabe)
          {
          case 'M': cout<<"1000"<<endl;
    
          case 'D': cout<<"500"<<endl;
    
          case 'C': cout<<"100"<<endl;
    
          case 'L': cout<<"50"<<endl;
    
          case 'X': cout<<"10"<<endl;
    
          case 'V': cout<<"5"<<endl;
    
          case 'I': cout<<"1"<<endl;
          }
    }   
    else
    {
    cout<<"Es handelt sich um keine roemische Zahl!";
    }  
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    

    Egal was ich bis jetzt probiert habe, die If Bedingung wird immer als True erkannt und er rauscht dann durch die Switch anweisung durch. (wenn ich dann z.b. K eingebe, bleibt das Fenster einfach leer.

    Wo liegt mein Fehler? Ich suche shcon seit ner knappen halben Stunde und finde ihn einfach nicht.

    Eine weitere Frage: Kann ich ihm irgendwie sagen, dass der nicht auf Groß/Kleinschreibung achten soll, oder muss ich da den ganzen Spaß nochmal mit allen Kleinbuchstaben tippen?

    P.S.: Bevor jemand fragt: Die Switchanweisung MUSS bleiben. Zumindest in irgendeiner Form.

    Bin um jede Hilfe dankbar 🙂



  • eingabe=='M'||'D'||'C'||'L'||'X'||'V'||'I')
    

    Einfach in

    (eingabe=='M') || (eingabe=='C' || (...) ...
    

    umwandeln.

    Desweiteren kannst du ein default-case beim switch angeben, das spart die if-Abfrage.



  • #include <iostream>
    
    using namespace std;
    
    int main(int argc, char *argv[])
    {
        char eingabe;
    
        /* Eingabe */
        cout<<endl;
        cout<<"Bitte roemische Zahl eingeben: ";
                     cin>>eingabe;
    
        system("cls");
    
        /*Umwandlung*/
    
        if(eingabe == 'M' || eingabe == 'D' || eingabe == 'C'|| eingabe == 'L' ||
           eingabe == 'X' || eingabe == 'V' || eingabe == 'I')
        {
            switch(eingabe)
            {
                case 'M': cout<<"1000"<<endl; break;
    
                case 'D': cout<<"500"<<endl; break;
    
                case 'C': cout<<"100"<<endl; break;
    
                case 'L': cout<<"50"<<endl; break;
    
                case 'X': cout<<"10"<<endl; break;
    
                case 'V': cout<<"5"<<endl; break;
    
                case 'I': cout<<"1"<<endl; break;
            }
        }
        else
        {
            cout<<"Es handelt sich um keine roemische Zahl!";
        }
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    

    Aber ich würde die if-Anweisung wegmachen und ein default in der switch-Anweisung nutzen. Außerdem musst du in jedem case am Schluss ein break schreiben, damit du nicht in das nächste case rutschst.

    Edit:
    knivil war ein Tick schneller :p



  • Wunderbar, funktioniert. Da wär ich ja im Leben nicht draufgekommen...

    Und wie kann man das mit Groß/Kleinschreibung elegant lösen?

    P.S.: Ich weiß, in der switch Reihe fehlen oben die Breaks.

    😃 Da war ich selber zu langsam^^

    Default in der switch meint vermutlich dass, was ich gesucht habe aber auch nicht gefunden habe.

    Ich wollte einfach noch einen case dranhängen wenn es keiner der Buchstaben ist. Aber ich kann da ja schlecht das restliche Alphabeth reinhängen. Gibts da sowas wie einen Platzhalter?



  • Thraciel schrieb:

    Und wie kann man das mit Groß/Kleinschreibung elegant lösen?

    int main()
    {
     char x;
     std::cin >> x;
    
     switch(x)
     {
       case 'm':
       case 'M':
         std::cout << "ein m!" << std::endl;
         break;
    
       /*...*/
    
       default:
         std::cout << "ungueltige eingabe!" << std::endl;
     }
    }
    

    bb



  • @unskilled

    Das würde aber auch auf alles 2mal Tippen rauslaufen...

    Edit: Das mit default hab ich...hatte da nur ein case stehengelassen 🙄



  • Thraciel schrieb:

    @unskilled

    Das würde aber auch auf alles 2mal Tippen rauslaufen...

    echt? wo denn?



  • naja ich muss nach wie vor

    case:'M'
    case:'m'

    schreiben. In diesem Programm ist das ja an und für sich kein Ding, ich dachte nur einfach für später mal man kann ihm das mehr oder weniger Global sagen, dass er nicht unterscheiden soll.



  • #include <locale>
    ...
    char eingabe;
    ...
    locale l;
    if(!islower(eingabe, l))
        eingabe = tolower(eingabe, l);
    switch(eingabe)
    {
        case 'm':
        ...
    }
    


  • char x;
    	std::cin >> x;
    
    	switch(tolower(x))
    	{
    	case 'm':
    		std::cout << "ein m!" << std::endl;
    		break;
    
    		/*...*/
    
    	default:
    		std::cout << "ungueltige eingabe!" << std::endl;
    	}
    


  • Vielen Dank, selten so schnell so umfassende Hilfe bekommen 🙂



  • du kannst dir auch mal std::tolower und std::toupper angucken - das bringt aber imho nur nachteile (z.bsp. wenn du ein zeichen angibst, was in großschreibweise nicht in nen char "passt" - z.bsp. 'ß')

    also:

    int main()
    {
      char x = std::toupper('ß', std::locale());
    }
    

    wird schief gehen...

    bb



  • ODer gleich so :p



  • Nur zum Verständnis: Bei deiner anfänglichen if-Abfrage if(eingabe == 'M' || 'L' ... wird, wenn du kein M eingibst, überprüft, ob der Ausdruck 'L' korrekt ist.
    Und da 'L' einen Zahlenwert von nicht 0 hat und alles, was nicht 0 ist, true ist, ist deine If-Bedingung immer wahr.



  • .. folgendes ist nichts für Anfänger, aber vielleicht ist es hier von Interesse:
    In C++ ist die Schnittstelle für die Eingabe std::istream (also z.B. cin) das gilt auch dann, wenn man das Zahlenformat ändert. Der C++-Standard stellt dafür eine sogenannte Facette std::num_get<> zur Verfügung, die sich um das Einlesen von Zahlen kümmert. Und diese kann man nach eigenem Ermessen überschreiben:

    #include <locale>
    #include <iostream>
    
    namespace roemisch
    {
        namespace
        {
            const char* zch = "MDCLXVI";
            const unsigned wert[] = { 1000, 500, 100, 50, 10, 5, 1, 0 };
        }
    }
    
    template< typename E >
    class RoemischGet : public std::num_get< E >
    {
    public:
        RoemischGet( std::size_t refs = 0 )
            : std::num_get< E >( refs )
        {}
    
    protected:
        virtual iter_type do_get( iter_type in, iter_type end, std::ios_base& str,
            std::ios_base::iostate& err, long& v ) const
        {
            int val = 0;
            int cnt = 0;
            const unsigned int* nr_prev = 0;
            for( const unsigned int* nr; in != end; ++in, ++cnt, nr_prev = nr )
            {
                char_type c = *in;
                nr = roemisch::wert;
                for( const char* p = roemisch::zch; *p ; ++p, ++nr )
                    if( char_type( *p ) == std::toupper( c, str.getloc() ) )
                        break;
                if( *nr == 0 )
                    break;
                else if( nr < nr_prev )
                {   // Subtraktionsregel ist nicht implementiert
                    err |= std::ios_base::failbit;
                    return in;
                }
                val += *nr;
            }
            if( in == end )
                err |= std::ios_base::eofbit;
            if( cnt == 0 )
                err |= std::ios_base::failbit;
            else
                v = val;
            return in;
        }
    };
    
    int main()
    {
        using namespace std;
        cin.imbue( locale( cin.getloc(), new RoemischGet< char > ) );
        for( int i; cout << "> " && cin >> i; )
            cout << i << endl;
        return 0;
    }
    

    Das sieht dann etwa so aus

    > X
    10
    > D
    500
    > MMX
    2010
    > XXXXII
    42
    

    Gruß
    Werner



  • Um mal Werners Beispiel zu folgen und ein wenig abzudriften sei hier noch gesagt, dass man römische Zahlen auch im Code (ohne Laufzeiteinbusse) benutzen kann. :p

    [Metaprogrammierung] - Römische Zahlen

    Wie viel Sinn das macht sei dahingestellt, aber als ein zur Fakultät Alternatives Einstiegsbeispiel für Metaprogrammierung ist das denke auch mal ganz nett. 🙂


Anmelden zum Antworten