Converting morse code to english text?

Hi, I wrote a program that converts an english text and vice versa. The text to code conversion works fine however my code to text doesn't exactly work well.For example when I type in ... for conversion, it should return a S but it returns it as ABC. Some one please, please help me out on how to fix this? Thank you.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
string engtomol (string, string[]);
string moltoeng (string, char[]);

int main ()
{
    char alpha[26] = {'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'}; 
    string morse[81] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."};
    string text, morsecode;
    char choice;
    char repeat='y';
 
while (repeat=='y')
{
    cout << "Select 1 to decode English text to Morse code.\nSelect 2 to encode Morse code to English text" << endl;
    cin >> choice;

    if (choice=='1')
    {
        cout << "NOTE. DO NOT INPUT A NON ENGLISH CHARACTER. THIS TRANSLATOR EXCLUSIVELY TRANSLATES ENGLISH TEXTS (CAPITALIZED AND NON CAPITALIZED).\n";
        cout << "Enter a text to translate, each word seperated by a space if you want to translate more than one word: ";
        cin.get();
        getline(cin,text);
        cout << "TEXT: " << text << endl;
        cout << "MORSE CODE: " << engtomol(text, morse) << endl;
    }
    else if (choice=='2')
    {
        cout << "Enter a morsecode to translate, each letter code seperated by a space. If you want to translate more than one word, have 3 spaces between each word (for example, ... --- ...   ... --- ...): ";
        cin.get();
        getline(cin,morsecode);
        cout << "MORSECODE: " << morsecode << endl;
        cout << "TEXT: " << moltoeng (morsecode, alpha) << endl;  
    }
    
    cout << "Would you like to continue? Press y to repeat. Press any other key to exit. ";
    cin >> repeat;
}
return 0;
}    



string engtomol (string text, string morse[])
{
    string morsevalue;
    string spacesbtwletters= " ";
    string spacesbtwwords = "  ";//2 spaces because im going to add it with spacesbtwletters so that it will = 3
for (int k=0; text[k]; k++)
    {
        if (text[k]!= ' ') //if the word(s) did not encounter a space
        {   text[k]=toupper(text[k]); //upper case letters and lower case letters are the same hence have the same appropriate morse code.
            morsevalue=spacesbtwletters+=morse[text[k]-'A']+" ";//A is the first value of the array. by subtracting its finding the appropriate morse code for each letters
        }
        if (text[k]==' ')
        {
            spacesbtwletters+=spacesbtwwords;//adds 3 spaces when there is a space between words
        }
    } 
return morsevalue; 
}

string moltoeng (string morsecode, char alpha[])//code to text function
{
    const int count=0;
    string tran;
    string spacesbtwlettercode= " ";
    string spacesbtwwordcode = " ";
for (int k=0; morsecode[k]; k++)
    {
    if (morsecode[k]!=' ')
    {
        tran=spacesbtwlettercode+=alpha[k];//A is the first value of the array. by subtracting its finding the appropriate
    }
    }
return tran; 
}

alpha[k] on line 76 is probably your problem.

basically you're going to have to parse the morse code string. Append everything you read in until you find a space (or you can use a string stream) then when you find the string, determine what letter that is, add that letter to the output and then reset it to an empty string.
Last edited on
hi giblit, i edited the code but now it returns opq.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
string moltoeng (string morsecode, char alpha[])
{
    string tran;
    string spacesbtwletters= " ";
    string spacesbtwwords = "   ";
for (int k=0; morsecode[k]; k++)
    {
    if (morsecode[k]!= ' ') //if the word(s) did not encounter a space
        {   
        tran=spacesbtwletters+=morsecode[k]+alpha[k];
        }
    } 
return tran; 
}


I still have no clue how to debug this..
First, why is line 11 an array size of 81 and not 26?

Second, yours look almost the same exact. You are going to need to pass the morse code array from your main to the function you do not need the alphabet array.


Third you need to find what position in the array the current morse letter is. Then based on the letter you can append something like 'A' + position



Here is one way

1
2
3
4
5
6
7
8
9
10
11
12
13
14
string morseToEnglish(string code, string morseCode[])
{
    std::istringstream ss(code); //stream to get the current letter
    std::string letter = ""; //current letter (morse)
    std::string output = ""; //output string

    while(ss >> letter) //get the current morse letter
    {
        //find that letter in morseCode array and output the position
       output += 'A' + position; //append the current letter
    }

    return output; //return the output
}


There are several ways to get the current letter and to find the letter.

Alternative for getting current letter:

1
2
3
4
5
6
7
8
9
std::string letter = "";
int i = 0;

//iterate over the entire string
    while(code[i] != ' ')    letter += code[i++];

    //do stuff with the letter as mentioned earlier

    letter = ""; //reset string 
Last edited on
i deleted the alphabet array and fixed the array size for the morse library as you mentioned (funny thing, when I started working on this program even though it declared the size to be 26 it gave me an error but now it works).

and as to finding the position, I deleted the statement in the function since I just wanted to see how the finding the position thing would work out, however it is not working as expected. in this code I wrote it returns a ?.

string moltoeng (string morsecode, string morse[])
{
    string findposition;
    int morselength = morsecode.length();
    string letter="";
    for (int k=0; morsecode[k]; k++)
    {
        if (morsecode[k]!=' ')
        {
            findposition=morselength-morsecode[k];
        }
    }
    return position;
}


Sorry i'm being so inquisitive here, I'm very new to the C++ world.
You have find position as a string instead of int :P

But anyways to do it the way you are it would be something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
string moltoeng(string morseCode, string morse[])
{
    int const characters = 26;

    std::string output = ""; //output for function

    int index = 0;
    while(index != morseCode.size())
    {
        //find current morse code
        std::string letter = "";
        while(morseCode[index] != ' ') letter += morseCode[index++];

       //find this code in the morse alphabet
       int position = 0;
       while(morse[positon] != letter && position < 26) ++position;

       output += 'A' + position;
       ++index; //to get rid of the space character.
    }

    return output;
}



There are more effective ways like using istringstream and/or unorderd_maps. You could also use for loops instead of while loops. But this is just to show you how you would do it.



P.S. Sorry it took so long to respond I just got back from the Phoenix Gun show :)
Last edited on
Hi giblit, so I edited the code as you have mentioned, but I keep on getting a segmentation fault: 11 error. I'll paste the error over here.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
string engtomol (string, string[]);
string moltoeng (string, string[]);

int main ()
{
    string morse[26] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."};
    string text, morsecode;
    char choice;
    char repeat='y';
 
while (repeat=='y')
{
    cout << "Select 1 to decode English text to Morse code.\nSelect 2 to decode Morse code to English text" << endl;
    cin >> choice;

    if (choice=='1')
    {
        cout << "NOTE. DO NOT INPUT A NON ENGLISH CHARACTER. THIS TRANSLATOR EXCLUSIVELY TRANSLATES ENGLISH TEXTS (CAPITALIZED AND NON CAPITALIZED).\n";
        cout << "Enter a text to translate, each word seperated by a space if you want to translate more than one word: ";
        cin.get();
        getline(cin,text);
        cout << "TEXT: " << text << endl;
        cout << "MORSE CODE: " << engtomol(text, morse) << endl;
    }
    else if (choice=='2')
    {
        cout << "Enter a morsecode to translate, each letter code seperated by a space. If you want to translate more than one word, have 3 spaces between each word (for example, ... --- ...   ... --- ...): ";
        cin.get();
        getline(cin,morsecode);
        cout << "MORSECODE: " << morsecode << endl;
        cout << "TEXT: " << moltoeng (morsecode, morse) << endl;  
    }
    
    cout << "Would you like to continue? Press y to repeat. Press any other key to exit. ";
    cin >> repeat;
}
return 0;
}    



string engtomol (string text, string morse[])
{
    int textlength = text.length();
    string morsevalue;
    string spacesbtwletters= " ";
    string spacesbtwwords = "  ";//2 spaces because im going to add it with spacesbtwletters so that it will = 3
for (int k=0; k<textlength; k++)
    {
        if (text[k]!= ' ') //if the word(s) did not encounter a space
        {   text[k]=toupper(text[k]); //upper case letters and lower case letters are the same hence have the same appropriate morse code.
            morsevalue=spacesbtwletters+=morse[text[k]-'A']+" ";//A is the first value of the array. by subtracting its finding the appropriate morse code for each letters
        }
        if (text[k]==' ')
        {
            spacesbtwletters+=spacesbtwwords;//adds 3 spaces when there is a space between words
        }
    } 
return morsevalue; 
}

string moltoeng(string morsecode, string morse[])
{
    int const characters = 26;
    std::string output = ""; //output for function
    int index = 0;
    while(index != morsecode.size())
    {
        //find current morse code
        std::string letter = "";
        while(morsecode[index] != ' ')
        {
            letter += morsecode[index++];
        }
       //find this code in the morse alphabet
       int position = 0;
       while(morse[position] != letter && position < 26)
       {++position;
       output += 'A' + position;
       ++index; //to get rid of the space character.
       }
    }

    return output;
}


and nice! hope you had fun!
Yeah I had fun, got some new toys to add to my collection :P

Also, I spot one potential error.


1
2
3
4
       {++position;
       output += 'A' + position;
       ++index; //to get rid of the space character.
       }


Basically that loop is just for finding the position in the array that that particular morse code is.

So for example if letter == ..-. then we will iterate until we find that in the morse array. Which would make position == 5 which is f.

Also, Sorry they should be < size and not != since it will break on the last letter :P

Also, the second while loop you probably want to make sure it is less than the size of string as well.


Though, I meant for you to modify it and not just copy paste :P Was trying to show you how it worked in the back end.

There is still a slight bug if there are any extra white spaces.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
string moltoeng(string morsecode, string morse[])
{
    std::size_t const characters = 26;
    std::string output = ""; //output for function
    std::size_t index = 0;
    std::size_t const size = morsecode.size();
    
    while(index < size)
    {
        std::string letter = "";
        while(morsecode[index] != ' ' && index < size)
        {
            letter += morsecode[index++];
        }

       //find this code in the morse alphabet
        int position = 0;
        while(morse[position] != letter && position < 26)
        {
            ++position;
        }
            
        output += 'A' + position;
        ++index; //to get rid of the space character.
       
    }

    return output;
}


Here is how I would personally do it
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <string>
#include <sstream>

std::string convertToEnglish(std::string morse, std::string const morseCode[]);

int main()
{
    std::string input = "";
    std::cout << "Please enter a string in morse code: ";
    std::getline(std::cin, input);
    
    std::string const morseCode[] = {".-", "-...", "-.-.", "-..", ".", "..-.",
    "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-",
    ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."};
    
    std::cout << convertToEnglish(input, morseCode) << std::endl;
    

    return 0;
}

std::string convertToEnglish(std::string morse, std::string const morseCode[])
{
    std::string output = "";
    std::string currentLetter = "";
    std::istringstream ss(morse);
    
    std::size_t const characters = 26;
    
    while(ss >> currentLetter)
    {
        std::size_t index = 0;
        while(currentLetter != morseCode[index] && index < characters)
        {
            ++index; //increment here so we don't have to decrement after the loop like if we put in the condition
        }
        
        output += 'A' + index;
    }
    
    return output;
}
Please enter a string in morse code: --. .. -... -... -.--
GIBBY


Ps you can probably pass by constant references too. I was just trying to quickly write up an example. You could also use a map instead of having to search for the index of the letter and if it contains it. Or you could use std::distance and std::find
Hey thanks gibit, though it doesn't show spaces when it encounters three spaces, I'll try to figure out a way to do that on my own.

Again, thanks a lot!
You could have a counter for spaces, and if you find 3 then append it to the output.
Topic archived. No new replies allowed.