Mosecode Übersetzer



  • Hallo Zusammen. Ich hab folgende Aufgabestellung, die ein Text in Morsecode übersetzen soll und umgekerht. Die Übersetzung in Morsecode funktioniert, nur wenn ich die Gegenprobe von Morsecode zu Text mache hab ich eine fehlerhafte Ausgabe. Kann mir vielleicht jemand helfen? Danke im Vorraus

    #include <iostream>
    #include <algorithm>
    #include <string>
    
    using namespace std;
    int main ()
    {
    {//Menü
    
    menue:
    cin.clear();
        cout <<endl;
        cout << " Willkommen" << endl;
        cout << " Was soll ausgeführt werden?: "<<endl;
        cout <<endl;
        cout << " |1| Text -> Morsecode "<<endl;
        cout << " |2| Morsecode -> Text "<<endl;
        int eingabe;
        cin >> eingabe;
    
    if (eingabe==1) {goto menu1;}//Text zu Morsecode
    if (eingabe==2) {goto menu2;}//Morse zu Text
    }
    //-----------------------------------------------------------------------------
    {
    
    menu1: // Text zu Morsecode
    cin.ignore();
    cin.clear();
    {
      const char letters[37] = {' ', 'a' ,'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };
        const string morseletters[37] = { " ", ".-", "-...", "-.-.", "___ . .", ".", ". . ___ .", "___ ___ .", ". . . .", ". .", ". ___ ___ ___", "___ . ___", ". ___ . .",  "___ ___", "___ .", "___ ___ ___", ". ___ ___ .", "___ ___ . ___", ". ___ .", ". . .", "_", ". . ___", ". . . ___", ". ___ ___", "___ . . ___", "___ . ___ ___", "___ ___ . .", ". ___ ___ ___ ___", ". . ___ ___ ___", ". . . ___ ___", ". . . . ___", ". . . . .", "___ . . . .", "___ ___ . . .", "___ ___ ___ . .", "___ ___ ___ ___ .", "___ ___ ___ ___ ___"};
      string textToChange = "";
      string newText = "";
      cout << "Gebe dein Text ein der in Morsecode übersetzt werden soll" << endl;
      getline(cin, textToChange);
      transform(textToChange.begin(), textToChange.end(), textToChange.begin(), ::tolower); //Konvertierung Eingabe in Kleinbuchstaben
    
      for (unsigned int i = 0; i < textToChange.size(); i++) {
        for (unsigned short j = 0; j < 37; j++) {
          if (textToChange[i] == letters[j]) {
            newText += morseletters[j];
            newText += "";
            break;
          }
        }
      }
    
      cout << "Text in Morse code" << endl << newText;
      int a;
      cin >> a;
      system ("PAUSE");
      goto menue;
    }
    }
     // Morsecode zu Text
    menu2:
    cin.ignore();
    cin.clear();
    
      const char letters2[37] =  {'  ', '.-', '-...', '-.-.', '___ . .', '.', '. . ___ .', '___ ___ .', '. . . .', '. .', '. ___ ___ ___', '___ . ___', '. ___ . .',  '___ ___', '___ .', '___ ___ ___', '. ___ ___ .', '___ ___ . ___', '. ___ .', '. . .', '_', '. . ___', '. . . ___', '. ___ ___', '___ . . ___', '___ . ___ ___', '___ ___ . .', '. ___ ___ ___ ___', '. . ___ ___ ___', '. . . ___ ___', '. . . . ___', '. . . . .', '___ . . . .', '___ ___ . . .', '___ ___ ___ . .', '___ ___ ___ ___ .', '___ ___ ___ ___ ___'};
      const string morseletters2[37] = { "  ", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"};
      string textToChange = "";
      string newText = "";
      cout << "Gebe dein Text ein der in Morsecode übersetzt werden soll" << endl;
      getline(cin, textToChange);
      transform(textToChange.begin(), textToChange.end(), textToChange.begin(), ::tolower);
    
      for (unsigned int i = 0; i < textToChange.size(); i++) {
        for (unsigned short j = 0; j < 37; j++) {
          if (textToChange[i] == letters2[j]) {
            newText += morseletters2[j];
            newText += "   ";
            break;
          }
        }
      }
    
      cout << "Text in Morse code" << endl << newText;
      int a;
      cin >> a;
      system ("PAUSE");
      }
    


  • @steven-w wie du schon selbst festgestellt hast, sind die Buchstaben des Morsealphabets vom Typ string und nicht char, wie im zweiten Versuch. Einfach tauschen geht also nicht.

    Deine Striche sind mal - und mal _



  • 2 Fragen:



  • Du hast in deinem zweiten Codeteil die Variablen (und dessen Datentypen) letters2 und morseletters2 vertauscht.
    Bei ersterem sollten eigentlich auch Warnungen vom Compiler erzeugt werden, da du mehrere Zeichen in ein char packst.

    Warum hast du sie überhaupt zweimal definiert? Du kannst doch dafür genauso letters und morseletters benutzen (mußt sie dann nur außerhalb der Blockklammern definieren).

    In Zeile 65 soll wohl folgendes stehen:

    cout << "Gebe deinen Morsecode ein, der in Text übersetzt werden soll" << endl;
    

    ?

    Und der Algorithmus ist auch falsch. Du mußt nicht nur einzelne char vergleichen, sondern die Morsecodes als Substrings.

    PS: Warum hast du vier verschiedene Zeichen im Morsecode: Punkt, Strich, Unterstrich und Leerzeichen?

    Und du solltest für die beiden Menüpunkte eigene Funktionen definieren (und auf goto verzichten).



  • @steven-w Copy&Paste hilft nicht beim Lernen! Also schreib das mal von Grund auf neu.

    Probiere mal einen der c++ Container, wie z.B. eine std::map:

    const std::map<unsigned char, std::string> morse_codes = {
    	{'a', ".-"}, 
    	{'b', "-..."},
    	...
    	{'x', "-..-"},
    	{'y', "-.--"},
    	{'z', "--.."},
    	{'1', ".----"},
    	...
    	{'9', "----."},
    	{'0', "-----"}
    };
    

    Vergleiche Deinen kopierten Code mit dem Internationalen Morse Alphabet. Da gibt es sogar Satzzeichen.

    Eine der benötigten Funktionen könnte dann ungefähr so aussehen:

    std::string string_to_morse(const std::string& text)
    {
    	std::string data;
    
    	for(unsigned char c text) {
    		// das '_' ist der Zeichen-Delimiter
    		data += "_" + morse_codes.find(std::tolower(c))->second;
    	}
    
    	return data;
    }
    

    Für die zweite Funktion würde ich mir mal std::getline, den const Iterator und die String-Vergleichsfunktion compare etwas näher ansehen. Bei dem Parameter 'delim' von getline kommt unser '_' wieder ins Spiel:

    std::string morse_to_string(const std::string& morse)
    {
    	std::string data;
    	std::string code;
    
    	std::istringstream is(morse);
    	while(std::getline(is, code, '_')) {
    
    		// Finde den code in der std::map morse_codes
    		// und füge den Buchstaben an data an.
    		std::map<unsigned char,std::string>::const_iterator it = morse_codes.begin();
    		// ab hier machst Du weiter...
    	}
    
    	std::cout << data << std::endl;
    }
    

    Viel Spass beim Basteln!

    Edit: Hinweise von wob umgesetzt.



  • @daMicha

    Danke für die Hilfe, ich schau mir das ganze an und werde wohl grundlegend damit nochmal neu anfangen.



  • @daMicha sagte in Mosecode Übersetzer:

    std::istringstream is(text);
    for(unsigned char c; is >> c; ) {

    Naja, warum gehst du hier eigentlich über eine Stream? Würde es nicht ein simples

    for (char c : text) {
        ...
    }
    

    auch tun?

    Und für morse_to_string bietet sich doch eine umgekehrte map an anstatt die Map von char nach morsecode nach dem passenden Value zu durchsuchen. Auch ist deine Signatur void morse2string(std::string morse) fragwürdig. Returnwert sollte std::string sein und der Parameter könnte const& vertragen oder ein std::string_view sein.



  • @wob sagte in Mosecode Übersetzer:

    for (char c : text) {
        ...
    }
    

    auch tun?

    Ja, das tut es. Und nach dem Ändern der Funktion sieht es sogar noch besser aus. 🙂

    Und für morse_to_string bietet sich doch eine umgekehrte map an anstatt die Map von char nach morsecode nach dem passenden Value zu durchsuchen. Auch ist deine Signatur void morse2string(std::string morse) fragwürdig. Returnwert sollte std::string sein und der Parameter könnte const& vertragen oder ein std::string_view sein.

    Stimmt auch, Danke für den Hinweis.

    std::string string_to_morse(const std::string& text);
    std::string morse_to_string(const std::string& morse);
    

    Ich wollte nur eine map verwenden um Tip-Fehler zu vermeiden.



  • @daMicha sagte in Mosecode Übersetzer:

    Ich wollte nur eine map verwenden um Tip-Fehler zu vermeiden.

    Die Rückwärts-Map kannst du doch einfach aus der Vorwärts-Map erstellen. Selbstverständlich sollte man nicht 2x die Zuordnung hinschreiben!
    Alternativ: https://www.boost.org/doc/libs/1_76_0/libs/bimap/doc/html/index.html (auch wenn ich mich mit der Boost-Dokumentation immer sehr schwer tue).



  • @wob sagte in Mosecode Übersetzer:

    Die Rückwärts-Map kannst du doch einfach aus der Vorwärts-Map erstellen.

    Definiere "einfach". Ich finde auf die Schnelle nur was mit Templates. Ob das dem OP wohl gut tut?



  • @daMicha sagte in Mosecode Übersetzer:

    @wob sagte in Mosecode Übersetzer:

    Die Rückwärts-Map kannst du doch einfach aus der Vorwärts-Map erstellen.

    Definiere "einfach". Ich finde auf die Schnelle nur was mit Templates. Ob das dem OP wohl gut tut?

    Hä? Deine Vorwärts-Map ist doch auch schon ein Template, weil eben std::map getemplatet ist.

    const std::map<unsigned char, std::string> morse_codes = {
            {'a', ".-"}, 
            {'b', "-..."},
            ...
    };
    
    [...]
    
    std::map<std::string, unsigned char> code_to_letter;
    for (const auto& l2c : morse_codes) 
        code_to_letter[l2c.second] = l2c.first;
    

    Diese for-Loop ist doch nun wirklich nicht kompliziert.



  • @wob ich hatte es inzwischen auch:

    // umgekehrte map initialisieren
    std::map<std::string, unsigned char> string_codes;
    for(std::map<unsigned char, std::string>::const_iterator it = morse_codes.begin(); it != morse_codes.end(); ++it) {
    	string_codes.insert(std::pair<std::string, unsigned char>(it->second, it->first));
    }
    

    Deins sieht besser aus, Du Profi!



  • @daMicha sagte in Mosecode Übersetzer:

    Deins sieht besser aus, Du Profi!

    Dein Code sieht halt nach C++98 aus. range-for und auto haben in C++11 vieles extrem vereinfacht.



  • @wob sagte in Mosecode Übersetzer:

    std::map<std::string, unsigned char> code_to_letter;
    for (const auto& l2c : morse_codes) 
        code_to_letter[l2c.second] = l2c.first;
    
    std::map<std::string, unsigned char> code_to_letter;
    for (const auto& [letter, code] : morse_codes) 
        code_to_letter[code] = letter;
    

    😉


Log in to reply