Umwandlung von Zahlen in Klartext



  • [quote="fragèè"]meinst du mit "englischem klartext" sowas wie "one-thousand-and-two"?[/quote]

    Ja,genau



  • das wird schwer, hab da mal ein makro(bzw. makros) bei einem 99bottles...-quellcode gesehen 😉 vielleicht spuckt google ja was aus



  • na so schwer ist das nicht. du brauchst die zahlen 1-9 als text und dann jeweils die endungen für die zehner, hunderter, tausender etc. dann zerlegt man die zahl in ihre einzelteile und fügt einfach das wort zusammen.

    aufpassen muss man nur bei den "unregelmäßigen" zahlen und den zahlen unter 20, da diese anders gebildet werden

    43 -> 40 + 3 -> four + ty + three
    19 -> 10 + 9 -> (umgekehrt) nine + teen
    12 -> 10 + 2 -> (umgekehrt) two + teen... oops, falsch, sonderfall.

    die sonderfälle lassen sich aber an einer hand abzählen:

    die zahlen unter 20, die zahlen 11 und 12.

    das englische macht es sogar einfacher, da die eins immer one heisst und nicht bei sowas wie "eins" und "eins-tausend... eintausend" unterschieden werden muss



  • Hab schon den ganzen Nachmittag gegoogled, aber leider nichts passendes gefunden.

    Soll eigentlich ne Aufgabe für Informartik 1 für Wirtschaftsingeniuere sein.
    Dachte eigentlich wäre leichter.



  • So hatte ich mir das auch gedacht, aber ich weiß nicht, wie ich die eingegeben Zahlen 1-9 im Programm einlesen muß, damit das Programm sie dann umwandelt.
    Ich bin nicht sehr mit den Befehlen vertraut.



  • na mach doch die zahl (du willst ja 'nur' bis 999.999 gehen) z.b. 10.000, erst du 1000 immer, dann hast du die thousend (wie man das auch imma schreibt), also 10000 : 1000 gleich 10 also ten-thousend das übrige durch hundert, 000 : 100 = 0, da brauchst du dann nen par extras, also wenn ne null is dann hörts halt auf und mit -ty und co.
    geht best. einfacher, aber ein wech isses^^

    gruß



  • mir war langweilig, hier mal eine lösung für die zahlen von 0 - 9999.

    müsste eigentlich alle zahlen korrekt darstellen, wenn ich noch richtig im kopf hatte, wie engländer ihre zahlen bauen 😉

    #include <cstdlib>
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <map>
    
    using namespace std;
    
    struct converter
    {    
        map<unsigned, string> literals;
        map<unsigned, string> specials;
        map<unsigned, string> xfixes;
        string interzero;
    
        converter()
        {        
            literals[1] = "one";
            literals[2] = "two";
            literals[3] = "three";
            literals[4] = "four";
            literals[5] = "five";
            literals[6] = "six";
            literals[7] = "seven";
            literals[8] = "eight";
            literals[9] = "nine";
    
            specials[0]  = "zero";
            specials[10] = "ten";
            specials[11] = "eleven";
            specials[12] = "twelve";
            specials[20] = "twenty";
            specials[30] = "thirty";
            specials[50] = "fifty";
            specials[80] = "eighty";
    
            xfixes[0] = "teen";
            xfixes[1] = "ty";
            xfixes[2] = "hundred";
            xfixes[3] = "thousand";
    
            interzero = "and";
        }
    
        string operator()(unsigned in)
        {
            if(strlen(specials[in].c_str())) return specials[in]; // "literale" sonderfälle
            if(!in) return specials[0];
            if(in < 10) return literals[in];
    
            string out;
    
            out = literals[in % 10]; // literal
            in /= 10;
            if(!in) return out;
    
            if(strlen(specials[(in % 10) * 10].c_str())) // zehner
                if(in % 10) out = specials[(in % 10) * 10] + out;
                else out = interzero + out;
            else
                out = literals[in % 10] + xfixes[1] + out;
            in /= 10;
            if(!in) return out;
    
            out = literals[in % 10] + xfixes[2] + out; // hunderter
            in /= 10;
            if(!in) return out;
    
            out = literals[in % 10] + xfixes[3] + out; // tausender
    
            return out;
        }
    };
    
    int main(int argc, char *argv[])
    {
        converter int2string;
        cout << int2string(0) << endl;
        cout << int2string(3) << endl;
        cout << int2string(12) << endl;
        cout << int2string(42) << endl;
        cout << int2string(80) << endl;
        cout << int2string(102) << endl;
        cout << int2string(1823) << endl;
    }
    

    (über den programmierstil lässt sich streiten)



  • paar includes und abfragen sind übrigens unnötig, hab den code nämlich tatsächlich getestet und zwischendrin kurz umgebaut, um ihn leichter lesbar zu machen 😉



  • Danke für die Hilfe,
    leider bin ich ja anfänger und mein Prof würde wohl merken, dass es nicht von mir ist. Hab mir jetzt was mit vielen "switch" gebaut, ist zwar nicht sehr elegant, aber klappt ganz gut.



  • Das ist eine interessante Aufgabe. Interessant deshalb, weil die IO-Libary des C++-Standards Features zur Verfügung stellt, wie man dies sehr schön in eine Applikation integrieren kann.

    Man stelle sich folgendes Programm vor ...

    #include <algorithm>
    #include <iterator>
    #include <iostream>
    #include <complex>
    
    #include "WriteOutNumber.h" // Facette zur Ausgabe von Integer-Variablen im Klartext
    #include "FacetSetter.h"
    
    int main()
    {
        using namespace std;
        const int zahlen[] = { 1, 2, 36, -500001 };
        {
            FacetSetter< WriteOutNumber > fs( cout ); // num_put-Facette auf 'WritOutNumber' umschalten
            copy( zahlen, zahlen + sizeof(zahlen)/sizeof(*zahlen),
                ostream_iterator< int >( cout, ", " ) );
            cout << "\nDie komplexe Zahl ist: " << std::complex< int >( -42, 7 ) << endl;
        }
        copy( zahlen, zahlen + sizeof(zahlen)/sizeof(*zahlen),
            ostream_iterator< int >( cout << "\n", ", " ) );
        cout << "\nDie komplexe Zahl ist: " << std::complex< int >( -42, 7 ) << endl;
    }
    

    Das diese Ausgabe erzeugt:

    one, two, thirtysix, minus fivehoundredthousandone,
    Die komplexe Zahl ist: (minus fourtytwo,seven)
    
    1, 2, 36, -500001,
    Die komplexe Zahl ist: (-42,7)
    

    Die Ausgabe von z.B. Zahlen innerhalb eines ostream's geschieht in einer Facette namens 'num_put'. Diese kann man durch eine eigene Facette gleichen Typs ersetzen, die die Zahlen dann entsprechend ausschreibt.

    Anbei noch die H-Dateien:

    // WriteOutNumber.h
    #ifndef NG_WRITEOUTNUMBER_H_
    #define NG_WRITEOUTNUMBER_H_
    
    #include <locale>
    #include <iterator>
    #include <string>
    
    namespace
    {
    namespace text
    {
        const std::string minus = "minus";
        const std::string numbers[] = {
            "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", 
                "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen",
                "twenty"
        };
        const std::string tausend = "thousand";
        const std::string hundert = "houndred";
        const std::string zehner = "ty";
        const std::string dreissig = "thirty";
    
        template< typename I >
        I print( I out, const std::string& txt )
        {
            return std::copy( txt.begin(), txt.end(), out );
        }
    }
    }
    
    template< typename E, typename OutIt = std::ostreambuf_iterator< E > >
    class basic_writeOutNumber : public std::num_put< E, OutIt >
    {
    public:
        typedef std::num_put< E, OutIt > base_type;
    
        explicit basic_writeOutNumber( std::size_t refs = 0 ) : base_type( refs ) {}
        virtual ~basic_writeOutNumber() {}
    
    protected:
        virtual iter_type do_put( iter_type out, std::ios_base& ios_, char_type fill,
            long v ) const
        {
            if( v < 0 )
            {
                out = text::print( out, text::minus );
                *(out++) = fill;
                v = -v;
            }
            return put( out, ios_, static_cast< unsigned long >( v ) );
        }
        virtual iter_type do_put( iter_type out, std::ios_base& ios_, char_type,
            unsigned long v ) const
        {
            return put( out, ios_, static_cast< unsigned long >( v ) );
        }
    
    private:
        iter_type put( iter_type out, std::ios_base& ios_,
            unsigned long v ) const
        {
            if( v >= 1000 )
            {
                out = put( out, ios_, v / 1000 );
                out = text::print( out, text::tausend );
                v %= 1000;
                if( v == 0 ) return out;
            }
            if( v >= 100 )
            {
                unsigned long h = v / 100;
                if( h > 0 )
                {
                    out = text::print( out, text::numbers[ h ] );
                    out = text::print( out, text::hundert );
                    v %= 100;
                    if( v == 0 ) return out;
                }
            }
            if( v >= sizeof(text::numbers)/sizeof(*text::numbers) )
            {
                unsigned long z = v / 10;
                if( z == 2 )
                {
                    // Sonderbehandlung für twenty
                    out = text::print( out, text::numbers[ 20 ] );
                }
                else if( z == 3 )
                {
                    // Sonderbehandlung für thirty
                    out = text::print( out, text::dreissig );
                }
                else
                {
                    out = text::print( out, text::numbers[ z ] );
                    out = text::print( out, text::zehner );
                }
                v %= 10;
                if( v == 0 ) return out;
            }
            return text::print( out, text::numbers[ v ] );
        }
    };
    
    typedef basic_writeOutNumber< char > WriteOutNumber;
    typedef basic_writeOutNumber< wchar_t > WWriteOutNumber;
    
    #endif
    

    und

    // FacetSetter.h - schaltet eine Facette ein und aus, nach dem RAI-Idiom
    #ifndef NG_FACETSETTER_H_
    #define NG_FACETSETTER_H_
    
    #include <iostream>
    #include <locale>
    
    template< typename F >
    struct FacetSetter
    {
        typedef std::basic_ios< typename F::char_type > ios_type;
        explicit FacetSetter( ios_type& strm, F* facet = new F )
            : m_strm( strm )
            , m_loc( m_strm.imbue( std::locale( strm.getloc(), facet ) ) )
        {}
        ~FacetSetter()
        {
            m_strm.imbue( m_loc );
        }
    private:
        FacetSetter( const FacetSetter& );
        FacetSetter& operator=( const FacetSetter& );
    
        // --   Members
        ios_type& m_strm;
        std::locale m_loc;
    };
    #endif
    

    Gruß
    Werner



  • Abgesehen davon, daß "fivety" vermutlich etwas albern aussieht und ich keine Sonderbehandlung für 11 bis 19 sehe, ist das ein netter Ansatz.

    (PS: Vor Jahren habe ich mal etwas ähnliches für den Bundeswettbewerb Informatik geschrieben - damals noch in Pascal - vielleicht findest du ja hier noch ein paar Anregungen (unter Archiv -> 1996/97))


Anmelden zum Antworten