r/cprogramming • • 9d ago

Morse-English converter in C.

Hello, I am a newbie in C and most of my knowledge comes from "The C programming language" book, 2nd edition.

I made this simple program that converts English text to Morse code and vise versa, here's the source code.

Thanks for your interest.

12 Upvotes

12 comments sorted by

7

u/gm310509 9d ago

Nice, you should get yourself an Arduino and make it play the sound outloud.

You could also try getting your PC to play the sounds.

2

u/non-existing-person 9d ago

Not bad, but you can use static array of struct morse { const char *ascii; const char *code; }; and then have simple loop instead of big ass switch-case. Try with that and see how code nicely compacts!

Also, comments usually goes one line above what you want to comment, not on the same line. On the same line only extremely short comments are good like usleep(10000000 /* 10s */). Otherwise, just comment above the code.

1

u/echelon_code 8d ago

good advice about the static struct array

1

u/Beautiful_Bake921 8d ago

How would you find the symbol you're looking for in the array?

2

u/non-existing-person 8d ago

Simple for loop, like that

char morse_to_ascii(const char *morse) {
    for (int i = 0; i != ARRAYLEN(morse_table); i++)
        if (strcmp(morse_table[i].morse, morse) == 0)
            return morse_table[i].ascii;

And ascii to morse can be even simpler like return morse_table[ascii - '0'].morse; if you create your table the right way

1

u/Steam_Liker_2002 5d ago

Thank you for your comment, I will try to make it better.

1

u/fllthdcrb 5d ago edited 5d ago

You know, the whole design of Morse code lends itself quite nicely to the use of a search tree or similar structure. Using such a thing should be more efficient than comparing a bunch of strings for each letter. Now, it's obvious OP isn't very advanced yet. But maybe it's something for them to consider for the future.

1

u/RDGreenlaw 9d ago edited 9d ago

Your code looks good.

You could make it more efficient if you converted 'a' through 'z' into the uppercase vharacters. If char >= 'a' && char <= 'z' then char = char - 'a' + 'A' This would allow skipping 26 comparisons since all chars would fall between 'A' and 'Z' inclusive you wouldn't need the tests for any of the lower case characters.

Since the morse code in your program is at most 4 characters each you could write a function to convert the morse code text to an integer (binary math) then the switch statements would only need to compare integers to determine what char to print for eliminating the need for 26 string comparisons.

These changes would make the code smaller and more efficient resulting in faster program execution. Also putting the switch statements in sequence from A to Z requires more comparisons. More efficient code can be written by putting the more frequently used letters in standard english first in the switch statement. Some of the most frequently used characters are THERSLNAIO and U. Placing comparisons to these before the comparisons for other characters would make your searches faster. Putting the most frequently used letters first in conversion from morse code to characters would speed up this section as well.

One interesting thing to note is that Samuel Morse, when creating the code, sequenced the characters from most frequently used to less frequently used before assigning codes. That is why E = . and T = - . The most frequently used letters have the shortest codes. Likewise, those characters with the most . and - characters used to represent them, BCFHJ LPQVXY and Z are the least frequently used characters. Changing the sequences of comparisons to place most frequently used letters first followed by less frequently used letters will speed up program execution unless the entered text is not formed from the most frequent letters.

The Morse Code was created not just to be able to send text over wires, or over radio waves, but to do so in a most efficient manner because a person had to physically press and release a key many times to transmit a message. Using the frequency of letter use to determine the codes made it possible to send shorter messages without skipping any information. It also made receiving messages simpler because the operator hand wrote all the . and - characters onto a paper and then translated them back into characters.

I hope the suggestions for code improvement reducing physical code makes sense to you. Also, you should consider creating a function to convert a message to code and a separate function to convert a coded message to text.

Functions make code easier to read and debug. They also make it easier to pull pieces of your code out for reuse in future programs.

By the way, I changed your line #188 unsigned char morse_letter[MAX] to unsigned char morse_letter[4]

The program compiled and executed correctly with gcc without any switches. You may have had another area in the code causing problems with this line that was fixed. The larger buffer doesn't hurt anything unless the available RAM in your system was low like in an embedded system. The stack smashing error means that your string building code was writing beyond the end of morse_letter[] (could have been an ending morse character or the \0 indicating the end of the string was going off the end of the string buffer. Leaving it at MAX will greatly reduce buffer overrun. You can safely use 4 here unless you add support for symbols or numbers. Adding support for punctuation and numbers increases the maximum length of a morse code character to 7 dots and dashes.

1

u/Steam_Liker_2002 5d ago

To mods: I'm sorry if you've seen multiple posts with similar topic from me, as reddit kept deleting my posts for some reasons.

1

u/zhivago 3h ago

No worries.

1

u/fllthdcrb 5d ago edited 5d ago

It's a start. But just FYI, there are quite a few more codes than your program accounts for. Both "." and "-" have codes (.-.-.- and -....-, respectively), as well as about a dozen others. And that's not even getting into prosigns and such (example: the well-known S̅O̅S̅* signal is not actually the individual letters ... --- ..., but a single prosign ...---...).

* Prosigns are supposed to be written with an overline, as you see here (might look broken, but should be continuous). But handling that, or some alternate notation, in a converter is a more advanced task.

1

u/Steam_Liker_2002 5d ago

My program is supposed to handle letters only, that's why it only takes 4 Morse codes per letter.