Morse Decoder/coder

The c++ programme does not give the complete output.
i.e.
Output
1
2
3
4
5
Decode MORSE code enter 1
Code Char to MORSE enter 2
1(input given)
Enter the morse code .- -..(input given)
Decoded string is a^@ (junk values)

Can anyone help?!?!
PS.It is for class and I am supposed to only use what I learnt.
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include<iostream.h>
#include<conio.h>
#include<string.h>
#include<stdio.h>
class codem
{
	char morse[155];
	char decode[15];
	char letter[25];
	public:
	inputm()
	{
		cout<<"Enter the morse code ";
		gets(morse);
	}
	decodem()
	{
		int j=0;
		int k=0;
		for(int i=0;morse[i]!='\0';i++)
		{
			if(morse[i]!=' ')
				morse[i]=decode[j++];
			else if(morse[i]==' ')
			{
				if(strcmp(decode,".-"))
				letter[k++]='a';
				else if(strcmp(decode,"-..."))
				letter[k++]='b';
				else if(strcmp(decode,"-.-."))
				letter[k++]='c';
				else if(strcmp(decode,"-.."))
				letter[k++]='d';
				else if(strcmp(decode,"-..-"))
				letter[k++]='x';
				else if(strcmp(decode,"-.--"))
				letter[k++]='y';
				else if(strcmp(decode,"--.."))
				letter[k++]='z';
				else
				cout<<"\nInvalid Input";
				strcpy(decode,"a");
				j=0;
			}//elseif closed
		}//for loop closed
	}//member fn decodem closed
	outputm()
	{
		cout<<"Decoded string is "<<letter;
	}
};//class closed
class codec
{
	char chr[50];
	public:
	inputc()
	{
		cout<<"Enter word to be encrypted ";
		gets(chr);
	}
	encodec()
	{
		for(int i=0;chr[i]<'\0';i++)
		{
			switch(chr[i])
			{
				case 'a':cout<<".-";
				break;
				case 'b':cout<<"-...";
				break;
				case 'c':cout<<"-.-.";
				break;
				case 'd':cout<<"-..";
				break;
				case 'x':cout<<"-..-";
				break;
				case 'y':cout<<"-.--";
				break;
				case 'z':cout<<"--..";
				break;
				default:cout<<"No MORSE code";
			}//switch close
		}//for loop close
	}//fn codec close
};//class close
void main()
{
clrscr();
      int op;
      codem m;
      codec c;
      cout<<"Decode MORSE code enter 1\nCode Char to Morse enter-2\n";
      cin>>op;
      if(op==1)
      {
	m.inputm();
	m.decodem();
	m.outputm();
      }
      else if(op==2)
      {
	c.inputc();
	c.encodec();
      }
      else
      {
	cout<<"Enter option 1 or 2";
      }
getch();
}

"iostream means Input Output STREAM hence iostream is used for input-output purposes. Such as for cin and cout functions for input and output respectively."
Last edited on
The c++ programme does not give the desired output.


What is the desired output?
Hello RRacer17,

In addition to what Repeater has said.

The c++ programme

No this is a C program. And you are mixing C and C++ code. This could be a potential problem.

salem c once wrote:

> #include<conio.h>
Obsolete since 1990, when the world stopped using DOS as a primary operating system.


And I do not believe there is an "<iostream.h>" header file at least not one that I have found yet.

Which now makes me need to ask what IDE are you using and what Standard is it compiling to.

The function clrscr() may be available to you, but not to everyone trying to work with this program.

If you are going to refer to this program as a C++ program then it should be a C++ program and not a mix.

Right now your code is not compilable for me without fixing all the problems.

I also notice that "main" should return an "int" not "void".

Also a few blank lines would help greatly. Just an example:
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
int main()
{
      clrscr();  // <--- Where is this defined and not everyone can use this.

      int op;
      codem m;
      codec c;

      //  <--- Right now you do not have the correct header file to use these.
      std::cout<<"Decode MORSE code enter 1\nCode Char to Morse enter-2\n";
      std::cin>>op;

      if(op==1)
      {
	m.inputm();
	m.decodem();
	m.outputm();
      }
      else if(op==2)
      {
	c.inputc();
	c.decodec();
      }
      else
      {
	cout<<"Enter option 1 or 2";
      }

      getch();  // <--- Not everyone can use this.
}

Some thoughts for now.

Hope that helps,

Andy
- Methods must be declared with a return type. Your should all return void
- After reading the number at line 210, you need to consume a newline.
- Line 21: for(int i=0;morse[i]<'\0';i++) what character is less than 0? I think you want for(int i=0;morse[i] != '\0';i++)

Your logic in decodem() is all messed up. The morse code string is stored in morse. But you're comparing against the string decode. And you're doing something with spaces. Explain what you're trying to do here and we can help you do it or suggest an alternative.

decodec() encodes the string? That makes my head hurt. Why not change it it encodec()?
I suggest that you concentrate on coding/decoding just two letters - 'a' and 'b'. Once you have the code doing those two correctly, you can add code for the rest of the letters. The advantage of doing it this way is that you only have to change code for two letters while debugging.


It would require rewriting most of this, but it would be smaller and more reliable to just create two arrays of c-strings. Onecontaining the morse encoding of the letters and the other encodes the digits:

1
2
3
4
5
6
7
8
9
10
11
12
13
const char *morseLetters[] = {
    ".-",    // a
    "-...", // b
    "-.-.", // c
    ...
    "--.." // z
};
const char *morseDigits[10] = {
    "-----",  // 0
    ".----",  // 2
    ...
    "----."  // 9
};


Now use these array to implement your encode/decode functions. Encoding is just an array lookup into the appropriate array. Decoding means searching the arrays for the string. Hmm... In a string of dashes and dots, how do you know where the letter breaks are?
HandyAndy wrote:
And I do not believe there is an "<iostream.h>" header file at least not one that I have found yet.

Before C++ had namespaces the headers were named in the common .h way.

When namespaces were introduced the headers were renamed in order not to clash with old code.

Implementations can choose to support the .h versions of the headers, basically just importing the regular header and doing "using namespace std". They used to do that but seem to have given up.
Some other fun regarding the standard header files:
- the <foobar.h> files must put the symbols in the global namespace and may put them in the std namespace.
- the <cfoobar> files may put the symbols in the global namespace and must put them in the std namespace.

I've had lots of fun (not) doing 20 years worth of deferred maintenance on code at work. The majority has just been getting things to work properly with the current header files.
Last edited on
Hello RRacer17,

Thinking about your program and how it does not work I offer this suggestion as a start:
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <iostream>
#include <limits>
#include <string>

class Encode
{
	std::string morse;
	std::string encode{ "a b c d" }; // <--- Set up for testing.
	//std::string letter; // <--- Not used.

	public:
		void UserInput();
		void EncodeString();
};

void Encode::UserInput() // <--- Put these here. Normally I put them after "main" or in a separate file.
{
	std::cout << "\n Enter the morse code (a b c): ";
	std::getline(std::cin, encode);
}

void Encode::EncodeString()
{
	for (size_t lc = 0; lc < encode.size(); lc++)
	{
		if (encode[lc] == ' ')
			continue;

		if (encode[lc] == 'a')
		{
			morse += ".-";
			morse += ' ';
		}
		else if (encode[lc] == 'b')
		{
			morse += "-.-.";
			morse += ' ';
		}
		else if (encode[lc] == 'c')
		{
			morse += "-..";
			morse += ' ';
		}
		else if (encode[lc] == 'd')
		{
			morse += ".";
			morse += ' ';
		}
	}

	morse.pop_back(); // <--- Removes the space at the end of the string.

	std::cout << "\n " << morse << std::endl;  // <--- Uses for testing. May not be something that you want to keep.

	return; // <--- Not needed in the function, but makes a good break point when testing. Remove when testing is finished.
}


int main()
{
	int op{ 1 }; // <--- Change to empty {}s when done testing.
	Encode encode;
	//codec decode; // <--- Not used yet.

	//std::cout << "\n Code Char to Morse enter - 1\n Decode MORSE code enter - 2\n Exit - 3\n Enter Choice: ";

	// <--- You may like this menu better. Use whichever you like.
	std::cout
		<< "\n 1. Code Char to Morse"
		<< "\n 2. Decode MORSE code"
		<< "\n 3. Exit"
		<< "\n Enter Choice: ";
	//std::cin >> op;

	std::cout << std::endl;  // <--- Used for testing. Remove when finished testing.

	while (!std::cin || (op < 1 || op > 3)) // <--- Check for a non numeric entry and validates input and.
	{
		if (!std::cin)
		{
			std::cout << "\n    Invalid entry! Must be a number.\n";

			std::cin.clear();
			std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
		}
		else if (op < 1 || op > 3)
		{
			std::cout << "\n    Entry out of range! Numbers are 1, 2 or 3\n";
		}

		std::cout << "\n Enter Choice: ";
		std::cin >> op;
	}
	
	// <--- Uncomment for normal use.
	//std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.

	switch (op) // <--- Or you can use your if else statements.
	{
		case 1:
			//encode.UserInput();
			encode.EncodeString();
			break;
		//case 2:
		//	break;
		case 3:
			break;
		default:
			break;
	}

	// <--- An alternative to using "system("pause")". Because you should not use "system" anything.
	// The next line may not be needed. If you have to press enter to see the prompt it is not needed. Just comment it out.
	//std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
	std::cout << "\n\n Press Enter to continue :";
	std::cin.get();

	return 0; // <--- Not required, but a good place for a break point.
}

This is a suggestion. I do not know what you can and can not use. I am also thing of a version that used an "enum" and an array. And a version that uses a "std::map". You will have to let me know if you have learned about either the "enum" or "std::map".

The not quite oblivious part is whiting this code in small parts. First I wrote the menu. Then i added the class "Encode" and worked on the class function "UserInput()". When that was working I adjusted the program to bypass the entering for "op" by initializing the variable to 1 when it was defined. Then in the case statement I could bypass calling "UserInput()" by initializing the string "encode" to "a b c d" or any variation of those four letters that you want. As dhayden suggested.

dhayden's idea of using the arrays is also a possibility.

In the function "EncodeString()" I just used the if/else if statements because they were easy to copy and change for now and it gives you a different approach than what you started with. You could just as easily use a "switch/case" here.

I feel that there is a better way than using two lines of "+=". At this time I seem to have a brain freeze on how to do this. Open to any suggestions or direction.

Initializing the string "encode" in the class worked for me, but it would be more proper to do this in the ctor of the class:
1
2
3
4
Encode::Encode()
{
    encode = "a b c d"; 
}


For the class "Decode" it could fundamentally start as a copy of "Encode", but would need some additional code to revers the process. Using a "stringstream" here would help along with "std::getline, letter, ' ')" where "letter" is defined as a "std::string". A thought for now.

@dhayden and dutch,

I already understand most of what you have said, so maybe you could tell me where "iostream.h" is located because I have not found one so far. Since that was my main point I would like to know where it is or if it even existed in the first place.

Hope that helps,

Andy
Dear Andy,

I have not learnt to use enum/std::map.
When I try to use
 
morse += ".-";

It shows an error for 'lvalue required'.
BTW iostream.h is used for (cin>>|cout<<) which is used for input(cin) and output(output).


Regards,

RRacer
Handy Andy wrote:
so maybe you could tell me where "iostream.h" is located
That's the old name of iostream. Many C++ generations ago when they added namespaces they stripped the ".h" suffix from the C++ standard header file names. At the same time, they changed the names of the standard C header files so that the C file somename.h became csomename.
@dhayden,

Thank you for the input and along with the little bit of research I have done I have come to realize that "iostream.h" is pre1998 standards which I have missed out on because my C classed ended before the '98 standards and I did not stay with the new changes.

When I started with books on C++ I do not recall ever seeing anything but "iostream" in the program examples. Then again the books may have been written after the '98 standards.

Of course this leads me to believe that the OP is using a very very old compiler and IDE that should be updated.

--------------------------------------------------------------------------------------------

Hello RRacer17,

I understand, but the "std::map" would have made thing much easier.


When I try to use
morse += ".-";


"morse" is defined as a "std::string" and the "+=" is overloaded to work with the "std::string". So if you did not include "<string>" in your header files and the compiler is not up to the C++11 standards there is a very good chance it will not work. You would need to use "strcat()" to do the same thing with the "char" array.

As soon as I finish checking the code I have I will let you see it.

BTW iostream.h is used for (cin>>|cout<<)...
. I understand this, but at the same time "iostream.h" is so old I have not seen or used it before. And I would guess that most compilers do not even use it these days.

Andy
Topic archived. No new replies allowed.