Vector Liste (Zahlen in Wörter ausgeben lassen - und anders herum)



  • Hallo liebe Community,

    ich habe ein Programm geschrieben, bei dem eine Liste mit Strings hinterlegt ist.

    Der Benutzer gibt eine Zahl (1, 2, 3,...) ein und erhält je nach Eingabe die Zahl in ausgeschriebener Form zurück.

    Das funktioniert auch sehr gut. Allerdings möchte ich jetzt noch implemtieren, dass die Funktion auch anders herum durchgeführt wird - sprich man gibt beispielsweise "sieben" ein und das Programm spuckt eine "7" aus.

    Habe schon recht intensiv nachgelesen und Google befragt, bin aber noch auf keine sinnvolle Idee gekommen.

    Vielen Dank vorab!

    Hier der bisherige Code meiner Konsolenanwendung:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    int main() {
    
        vector<string> word(10);
        word[0] = "null";
        word[1] = "eins";
        word[2] = "zwei";
        word[3] = "drei";
        word[4] = "vier";
        word[5] = "fünf";
        word[6] = "sechs";
        word[7] = "sieben";
        word[8] = "acht";
        word[9] = "neun";
    
        cout << "Bitte geben Sie eine Zahl ein: ";
    
        int num = 1;
        cin >> num;
    
        cout << "Ihre Eingabe war: " << word.at(num) << endl << endl;
    
        return 0;
    }
    


  • Probiere es doch mit einem struct, das einen int und einen string enthält. Zum Beispiel

    struct Zahl{
    std::string wort;
    int zahl;
    }
    

    Speicher dann das in einer Liste mit richtigem Inhalt und suche je nachdem, was der Nutzer eingibt in der Liste entweder nach dem wort oder nach der Zahl und gib das andere aus

    Edit:
    Es gibt von C++ auch im STL eine Klasse, die zwei Objekte kombiniert, ich kenne mich damit aber nicht so ganz aus.

    Edit2:
    Ach, und du könntest deine Liste durchlaufen und dann die Position ausgeben. Das setzt voraus, dass Differenz zwischen Zahl und Elementposition immer gleich ist. Ich dachte an so etwas:

    int ausgabe = 1;
    for(size_t i = 0; i < word.size(); ++i){
       if(word[i] == eingabe){
          ausgabe = i + 1;
          break;
       }
    }
    std::cout << ausgabe;
    

    Das problem ist, dass du einen impliziten typecast hast von unsigned int (size_t) nach signed int. Deswegen ist das nicht wirklich elegant.



  • Lass dir einen std::string eingeben. Diesen schiebst du in einen Stringstream aus dem versuchst eine Zahl zu extrahieren. Wenn es klappt hast du deine numerische Zahl. Failt es, dann extrahier einen String und dann hast du deine ausgeschriebene Zahl. Etwaige Fehler wie falsche Zahleneingaben (z.b. zrei statt zwei) musst du natürlich irgendwo abfangen.

    int main()
    {
    	std::string input;
    
    	std::cin >> input;
    
    	std::stringstream ss(input);
    
    	int zahl;
    	ss >> zahl;
    
    	if ( ss )
    		std::cout << "Numerische Zahl eingegeben: " << zahl << std::endl;
    	else
    	{
    		ss.clear();
    		std::string nummer;
    		ss >> nummer;
    
    		std::cout << "Ausgeschreibene Zahl eingegeben: " << nummer << std::endl;
    	}
    
    	return 0x0;
    }
    

    So etwa, aber schön ist das nicht...



  • Und was ist jetzt deine Frage?



  • Skym0sh0 schrieb:

    return 0x0;
    

    Funktioniert das Programm besser, wenn man die Null hexadezimal zurück liefert?



  • Skym0sh0 schrieb:

    ...

    Er möchte aber bei Eingabe von 7 die Ausgabe "sieben" und bei Eingabe von "sieben" die Ausgabe 7 haben ...

    #include <iostream>
    #include <vector>
    #include <string>
    
    using namespace std;
    
    int main() {
    
        vector<string> word(10);
        word[0] = "null";
        word[1] = "eins";
        word[2] = "zwei";
        word[3] = "drei";
        word[4] = "vier";
        word[5] = "fünf";
        word[6] = "sechs";
        word[7] = "sieben";
        word[8] = "acht";
        word[9] = "neun";
    
        cout << "Bitte geben Sie eine Zahl ein: ";
    
        string num;
        cin >> num;
    
        int i;
        for(i = 0; i < word.size(); ++i)
           if(word[i] == num)
              cout << "Ihre Eingabe war: " << i << endl << endl;
    
        if(i == word.size())
           cout << "Ihre Eingabe " << num << " habe ich nicht gespeichert\n";
    
        return 0;
    }
    

    ungetestet.



  • manni66 schrieb:

    Skym0sh0 schrieb:

    return 0x0;
    

    Funktioniert das Programm besser, wenn man die Null hexadezimal zurück liefert?

    Sicher nicht.



  • kralo9 schrieb:

    manni66 schrieb:

    Skym0sh0 schrieb:

    return 0x0;
    

    Funktioniert das Programm besser, wenn man die Null hexadezimal zurück liefert?

    Sicher nicht.

    Klar tuts das. Probiers mal, das macht dich zum Ultra-M3g4-H3xxx00rZ!



  • Skym0sh0 schrieb:

    kralo9 schrieb:

    manni66 schrieb:

    Skym0sh0 schrieb:

    return 0x0;
    

    Funktioniert das Programm besser, wenn man die Null hexadezimal zurück liefert?

    Sicher nicht.

    Klar tuts das. Probiers mal, das macht dich zum Ultra-M3g4-H3xxx00rZ!

    D4$ 1$7 J4 M41 V011 1337 !!!


  • Mod

    Aus Spaß für alle Zahlen < 100:

    #include <stdexcept>
    #include <string>
    
    std::string from_number( unsigned i )
    {
    	char const* einer []{ "null", "ein", "zwei", "drei", "vier", "fuenf", "sechs", "sieben", "acht", "neun",
    	                      "zehn", "elf", "zwoelf", "dreizehn", "vierzehn", "fuenfzehn", "sechszehn", "siebzehn", "achtzehn", "neunzehn" };
    	char const* zehner[]{ "zwanzig", "dreissig", "vierzig", "fuenfzig", "sechzig", "siebzig", "achtzig", "neunzig" };
    
    	if( i < 20 )
    		if(i == 1)
    			return "eins";
    		else
    			return einer[i];
    	else if( i < 100 )
    	{
    		std::string suffix = zehner[i/10-2];
    
    		auto rest = i%10;
    		if( rest )
    			return std::string{einer[rest]} + "und" + suffix;
    
    		return suffix;
    	}
    
    	throw std::invalid_argument{""};
    }
    
    #include <iostream>
    
    int main()
    {
    	for( unsigned i = 0; i != 100; ++i )
    		std::cout << from_number(i) << '\n';
    }
    


  • Vielen, vielen Dank schon mal für die hilfreichen Antworten. Habe es zwar noch nicht wirklich hinbekommen, aber jetzt kann ich weitersuchen /-arbeiten.



  • Dereferenzierungsoperator, musst du unbedingt {} als Konstruktorsyntax verwenden.
    Diese Syntax ist unter gewissen Umständen einfach nur lästig und kann zu ungewollten Ergebnissen führen, weswegen man dann doch auf () ausweichen muss, was dazu führt, dass die "vereinheitlichte Initialisierung" gar nicht mehr vereinheitlicht ist, und man direkt () hätte verwenden können.
    Und deine Exceptionfehlermeldungen sind einfach nur informativ.


  • Mod

    Nathan schrieb:

    Und deine Exceptionfehlermeldungen sind einfach nur informativ.

    Das sollen sie nicht sein. Bei Exceptions reicht der Typ.
    Edit: Ich würde nicht auf die Idee kommen, dem User die Exception-Fehlermeldung auszugeben - und was soll ich sonst damit?

    Eigentlich sollte man vielleicht doch einen leeren String zurückgeben. 💡

    Dereferenzierungsoperator

    Wen meinst du? 😕

    Ja, Marcus hat mich schlussendlich umbenannt. 👍

    Diese Syntax ist unter gewissen Umständen einfach nur lästig und kann zu ungewollten Ergebnissen führen, weswegen man dann doch auf () ausweichen muss, was dazu führt, dass die "vereinheitlichte Initialisierung" gar nicht mehr vereinheitlicht ist, und man direkt () hätte verwenden können.

    Siehe diesen GotW-Artikel, insbesondere Abschnitt 3/4.



  • Arcoth schrieb:

    Nathan schrieb:

    Und deine Exceptionfehlermeldungen sind einfach nur informativ.

    Das sollen sie nicht sein. Bei Exceptions reicht der Typ.
    Edit: Ich würde nicht auf die Idee kommen, dem User die Exception-Fehlermeldung auszugeben - und was soll ich sonst damit?

    Eigentlich sollte man vielleicht doch einen leeren String zurückgeben. 💡

    Es ist für dich klarer.
    Wenn du ein riesiges Projekt hast und irgendwo in deiner main ein invalid argument auftauchst, weißt du dann direkt, woher das kommt?
    Nein. Deshalb kurz in einer Fehlermeldung wenigstens den Funktionsnamen erwähnen.

    Diese Syntax ist unter gewissen Umständen einfach nur lästig und kann zu ungewollten Ergebnissen führen, weswegen man dann doch auf () ausweichen muss, was dazu führt, dass die "vereinheitlichte Initialisierung" gar nicht mehr vereinheitlicht ist, und man direkt () hätte verwenden können.

    Siehe diesen GotW-Artikel, insbesondere Abschnitt 3/4.

    Ja, Herb Sutter bringt Argumente dafür. Toll. Und?
    Das einzige Argument, was für mich zählt ist der "vexing parse".
    Ich verwende keine structs ohne Konstruktor und schreibe keinen generischen Code, der irgendetwas initialisieren soll.
    Um initializer_list-Konstruktoren aufzurufen, verwende ich natürlich {}, die Arrayinitialisierung zählt für mich dazu.
    Aber in allen anderen Fällen, nutz ich (). Ich erwisch so immer die richtigen Konstruktoren und hat für mich auch keine negativen Effekte.


  • Mod

    Nein. Deshalb kurz in einer Fehlermeldung wenigstens den Funktionsnamen erwähnen.

    Habe ich gerade perfekten und an deine Gewohnheiten angepassten Code liefern wollen? Das war auf die Schnelle hin konstruiert, und kein universales Etwas!

    Wenn du ein riesiges Projekt hast und irgendwo in deiner main ein invalid argument auftauchst, weißt du dann direkt, woher das kommt?

    Wieso will ich nur wissen, woher das kommt? Ich möchte auch wissen, wann der Fehler auftrat, was das Funktionsargument war, ich möchte den Call-Stack sehen, usw. Kurz: Ich möchte debuggen.

    Hast du es jetzt nötig, einen nebenbei geschriebenen, funktionierenden Code auf solche lächerlichen Nebensächlichkeiten zu analysieren, die nicht mal irgendwelche Allgemeingültigkeiten sind? Wenn du das unbedingt ausdiskutieren willst, öffne einen neuen Thread, aber fülle den hier nicht mit so einer Kritik.

    Aber in allen anderen Fällen, nutz ich (). Ich erwisch so immer die richtigen Konstruktoren und hat für mich auch keine negativen Effekte.

    Wen interessiert es, was du benutzt? Du benutzt, was du benutzt, und ich tue, was ich für richtig halte. Du krempelst das hier irgendwie zu einer Diskussion über Uniform-Initialization um.

    Verstehe mich bitte nicht falsch - 🙂 - das hat hier alles einfach nichts zu suchen, es war nur ein Beispiel für den TE, an dem ich immer noch nichts auszusetzen habe. Außer, dass man wohl einen leeren String zurückgeben könnte, anstelle einer Exception.



  • Arcoth schrieb:

    Nein. Deshalb kurz in einer Fehlermeldung wenigstens den Funktionsnamen erwähnen.

    Habe ich gerade perfekten und an deine Gewohnheiten angepassten Code liefern wollen? Das war auf die Schnelle hin konstruiert, und kein universales Etwas!

    Wie das war kein universales Etwas? 😉

    Wenn du ein riesiges Projekt hast und irgendwo in deiner main ein invalid argument auftauchst, weißt du dann direkt, woher das kommt?

    Wieso will ich nur wissen, woher das kommt? Ich möchte auch wissen, wann der Fehler auftrat, was das Funktionsargument war, ich möchte den Call-Stack sehen, usw. Kurz: Ich möchte debuggen.

    Naja, beim invalid_argument weiß man eigentlich, sobald man die Funktion weiß wo das Problem an der Sache ist und muss nicht großartig debuggen.

    Hast du es jetzt nötig, einen nebenbei geschriebenen, funktionierenden Code auf solche lächerlichen Nebensächlichkeiten zu analysieren, die nicht mal irgendwelche Allgemeingültigkeiten sind? Wenn du das unbedingt ausdiskutieren willst, öffne einen neuen Thread, aber fülle den hier nicht mit so einer Kritik.

    Hast recht, gehört hier nicht hin. 🙂

    Aber in allen anderen Fällen, nutz ich (). Ich erwisch so immer die richtigen Konstruktoren und hat für mich auch keine negativen Effekte.

    Wen interessiert es, was du benutzt? Du benutzt, was du benutzt, und ich tue, was ich für richtig halte. Du krempelst das hier irgendwie zu einer Diskussion über Uniform-Initialization um.

    Eigentlich hat mich an {} nur gestört, dass das für einen Anfänger evtl. unverständlich ist. Warum ich das nicht geschrieben habe, sondern stattdessen diese Diskussion losgetreten habe, weiß ich auch nicht. 😃



  • Was für Anfänger (un)verständlich ist, und was nicht, hat Sone noch nie interessiert ...


  • Mod

    Belli schrieb:

    Was für Anfänger (un)verständlich ist, und was nicht, hat Sone noch nie interessiert ...

    Und was genau war daran nicht verständlich? Um die vier Zeichen?

    Und nicht einmal die. Dass ich einen String erzeuge, um zwei weitere an ihn dranzuhängen, ist intuitiv klar.



  • Ich habe hier nichts konkret kritisiert, sondern nur geäußert, was mir in anderen, älteren Postings/Threads oft aufgefallen ist.



  • Das Thema Ausgabe von Zahlen als Text hatten wir schon mal im Forum


Anmelden zum Antworten