简体   繁体   中英

C Morse code converter shows no error in compiler but doesn't work

I am trying to write a simple program that takes a string input and then converts it into morse code.

When I compile the code and run it, I get no errors but it sometimes gives an output, sometimes doesn't, sometimes gives only the half of it. I can kind of understand that the algorithm that I use right now can be a bit slow to convert a big string but it does the same behaviour for even one character.

So what is wrong about my code?

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main()
{
    char characters[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'};
    char *morse[26] = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--"," -.","---",".--.","--.-",".-."," ...","-","..-","...-",".--","-..-","-.--","--.."};
    char input[25];
    char *output[25];
    gets(input);

    int i = 0, k = 0; //Make all of the chars uppercase to compare with the array.
    while(i < 25) {
        input[i] = toupper(input[i]);
        while(input[i] != characters[k]){
            k++;
        }
        output[i] = morse[k]; //Assign the according morse code to the output's pointers.
        i++;
    }

    int n = 0;
    while(n < 25){
        if (output[n] != NULL){  //Print out everything except empty parts
            printf("%s", output[n]);
            n++;
        }
        else{
            break;
        }
    }
    return EXIT_SUCCESS;
}  

You need to set k back to zero every time you search characters . Since you don't do this, you start your search from the position that the last search ended. If the next character is earlier in the alphabet, you won't find it and the search will read outside the array.

Also, if any of the input characters aren't letters, the search will never find it. The loop has no check for this.

A simpler method would be to first check isalpha() to make sure that the input is a letter, and then calculate input[i] - 'A' and use that as the index into morse .

When processing input you should stop when you get to the null terminator, not go all the way to i = 24 .

int i = 0;
while (input[i]) {
    if (isalpha(input[i])) {
        input[i] = toupper(input[i]);
        output[i] = morse[input[i] - 'A'];
    } else {
        output[i] = NULL;
    }
    i++;
}

Some remarks :

  • while(i < 25) must be while(input[i] != 0)

  • you also need to reset k to 0 in while(input[i] != 0) (if using the associated loop)

  • do not use gets but fgets

  • you also need to change while(n < 25) by while (n < i) . Your output[n] != NULL is not a protection because output is not initialized to NULL, so you access to non initialized value with the associated undefined behavior

  • you need to read only letter else while(input[i] != characters[k]) will go out of characters . It is also expensive to search for the code through a loop, just use character code - 'A' to be an index

Finally a proposal :

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main()
{
    const char * const morse[] = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--"," -.","---",".--.","--.-",".-."," ...","-","..-","...-",".--","-..-","-.--","--.."};
    char input[25];
    const char *output[25];

    if (fgets(input, sizeof(input), stdin) == NULL)
      return 0;

    int i = 0; //Make all of the chars uppercase to compare with the array.

    while((input[i] != 0) && isalpha(input[i])) {
      char c = toupper(input[i]);

      output[i++] = morse[c - 'A']; //Assign the according morse code to the output's pointers.
    }

    int n = 0;
    while (n < i)
      printf("%s", output[n++]);

    putchar('\n');

    return EXIT_SUCCESS;
}  

Compilation and execution :

pi@raspberrypi:/tmp $ gcc -g -Wextra mo.c
pi@raspberrypi:/tmp $ ./a.out
SOS
 ...--- ...

Use fgets to get input of variable length (just give it a character pointer) Use strlen to get the length input to control your loop. You might also want to reset the value of k when i is incremented so that you don't run out of bounds in the characters array.

Barmar's comment above is correct. In addition to that, your program depends on the user entering a string that consists entirely of characters. What do you think will happen in your inner while loop if your string contains, say, a "1"?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM