En este post vamos a implementar un traductor de código Morse en C. Veremos cómo codificar o transformar código Morse usando el lenguaje C.

Por ejemplo, haremos que la palabra HOLA se convierta a su equivalente .... --- .-.. .- y viceversa, logrando al final un traductor Morse.

Las equivalencias

Cada letra tiene un código que lo representa; yo me he basado en el siguiente archivo que contiene la equivalencia de cada letra con su respectivo código.

Signo,Código
A,.-
B,-...
C,-.-.
CH,----
D,-..
E,.
F,..-.
G,--.
H,....
I,..
J,.---
K,-.-
L,.-..
M,--
N,-.
Ñ,--.--
O,---
P,.--.
Q,--.-
R,.-.
S,...
T,-
U,..-
V,...-
W,.--
X,-..-
Y,-.--
Z,--..
0,-----
1,.----
2,..---
3,...--
4,....-
5,.....
6,-....
7,--...
8,---..
9,----.
.,.-.-.-
",",--..--
:,---...
?,..--..
',.----.
-,-....-
/,-..-.
comilla doble,.-..-.
@,.--.-.
=,-...-
!,−.−.−−

El algoritmo del traductor de Morse a C

Esto es muy simple, solo hay que buscar la equivalencia de cada letra o de cada código Morse; para ello podemos tomar varios enfoques pero yo he elegido el de poner dos arreglos; uno con Morse y otro con ASCII, con cada valor equivalente en el mismo índice:

// Código y signo iguales deben estar en el mismo índice
char *codigosMorse[] = {
        ".-", "-...", "-.-.", "-..",
        ".", "..-.", "--.", "....", "..",
        ".---", "-.-", ".-..", "--", "-.",
        "---", ".--.", "--.-", ".-.", "...",
        "-", "..-", "...-", ".--", "-..-",
        "-.--", "--..", "-----", ".----", "..---",
        "...--", "....-", ".....", "-....", "--...",
        "---..", "----.", ".-.-.-", "--..--", "---...",
        "..--..", ".----.", "-....-", "-..-.", ".--.-.",
        "-...-", ".-..-.", "-.-.--",};

char *simbolosAscii[] = {"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", "0", "1", "2",
                         "3", "4", "5", "6", "7",
                         "8", "9", ".", ",", ":",
                         "?", "'", "-", "/", "@",
                         "=", "\"", "!",};

Por ejemplo, la letra A equivale a .- y el símbolo ! equivale a -.-.--, están en distintos arreglos pero misma posición.

  • Cada que se quiere convertir de Morse a ASCII se busca el índice del código Morse a transformar, y luego se accede con ese índice pero al arreglo de simbolosAscii.
  • Lo mismo para transformar de ASCII a Morse, se busca el índice del símbolo ASCII y se accede al arreglo codigosMorse.

Esto sería más fácil si en C existieran los diccionarios, pero no existen y su implementación es cuestión de otro post.

Nota: otro enfoque más óptimo (en cuanto a rendimiento, para no buscar el elemento por cada símbolo) sería usar múltiples sentencias if o un diccionario.

Nota 2: si notas el algoritmo muy pesado, la verdad es que no lo es, lo pesado o complejo es trabajar con cadenas en C; si esto fuera otro lenguaje con mayor soporte de strings, nos llevaría menos de la mitad de código hacer el traductor de código Morse.

Funciones y ayudantes del traductor de Código Morse en C

Necesitamos funciones para dividir el algoritmo y hacerlo más fácil de resolver. También viene bien saber la longitud del arreglo, la cual se calcula así:

const int NUMERO_CODIGOS = sizeof(codigosMorse) / sizeof(codigosMorse[0]);

Lo calculamos con cualquier arreglo porque se supone que ambos arreglos miden lo mismo.

Después necesitamos el índice de cada código Morse o cada código ASCII:

int buscarIndiceDeMorse(char *codigo) {
    for (int x = 0; x < NUMERO_CODIGOS; x++) {
        if (strcmp(codigosMorse[x], codigo) == 0) {
            return x;
        }
    }
    return -1;
}

int buscarIndiceDeAscii(char signo) {
    // Convertir char a string
    char cadenaTemporal[2];
    cadenaTemporal[0] = signo;
    cadenaTemporal[1] = '\0';
    for (int x = 0; x < NUMERO_CODIGOS; x++) {
        if (strcmp(simbolosAscii[x], cadenaTemporal) == 0) {
            return x;
        }
    }
    return -1;
}

Son funciones que simplemente devuelven el índice del símbolo o código.

En la función para buscar el índice del código ascii creamos una cadena temporal, o mejor dicho, lo que equivale a una cadena o string en C, esto es para que strcmp (que compara cadenas) funcione.

Codificar Morse con C

Ahora veamos la siguiente función que convierte un mensaje a su equivalente en Morse. Leemos el mensaje con fgets y luego simplemente imprimimos cada equivalencia:

void demostrarCodificacionMorse() {
//    char mensaje[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,:?'-/@=\"!";
    char mensaje[LONGITUD_MENSAJE];
    printf("Mensaje a transformar en Morse: \n");
    fgets(mensaje, LONGITUD_MENSAJE, stdin);
    mensaje[strcspn(mensaje, "\r\n")] = 0; // Remover salto de línea
    // Recorremos la cadena y transformamos cada letra
    int i = 0;
    while (mensaje[i]) {
        // Convertir a mayúscula porque tenemos equivalencias solo para mayúsculas
        // y Morse no especifica minúscula
        char letraEnMayuscula = (char) toupper(mensaje[i]);
        int indice = buscarIndiceDeAscii(letraEnMayuscula);
        char *codigoMorse = codigosMorse[indice];
        // Aquí puedes hacer lo que gustes con el morse, yo simplemente lo imprimo
        printf("%s ", codigoMorse);
        i++;
    }
}

Estamos convirtiendo a mayúscula cada letra o símbolo pues en las equivalencias todo está en mayúscula. Cuando tenemos el código Morse lo imprimimos; como lo dije, puedes hacer cualquier cosa con él.

Decodificar Morse con C

Como queremos que este sea un traductor de código Morse en C necesitamos también decodificar un mensaje en Morse.

Para esto, vamos a hacer que cada símbolo Morse esté separado por un espacio; luego usamos strtok (algo como el split de C) y separamos la cadena por espacios.

void demostrarDecodificacionMorse() {
//    char mensaje[] = ".- -... -.-. -.. . ..-. --. .... .. .--- -.- .-.. -- -. --- .--. --.- .-. ... - ..- ...- .-- -..- -.-- --.. ----- .---- ..--- ...-- ....- ..... -.... --... ---.. ----. .-.-.- --..-- ---... ..--.. .----. -....- -..-. .--.-. -...- .-..-. -.-.--";
    // Aquí define tu mensaje separado por espacios
    char mensaje[LONGITUD_MENSAJE];
    printf("Mensaje Morse a decodificar:\n");
    fgets(mensaje, LONGITUD_MENSAJE, stdin);
    mensaje[strcspn(mensaje, "\r\n")] = 0; // Remover salto de línea
    char delimitador[] = " ";
    // Separamos la cadena por espacios. Más información sobre strtok en https://parzibyte.me/blog/2018/11/13/separar-cadena-delimitadores-c-strtok/
    char *token = strtok(mensaje, delimitador);
    if (token != NULL) {
        while (token != NULL) {
            // Obtener cuál índice tiene este código
            int indice = buscarIndiceDeMorse(token);
            // Aquí puedes hacer lo que gustes con el ascii, yo simplemente lo imprimo
            char *ascii = simbolosAscii[indice];
            printf("%s", ascii);
            token = strtok(NULL, delimitador);
        }
    }
}

Ahora hacemos casi lo mismo, solo que agregamos la implementación para separar la cadena. Después obtenemos el índice con buscarIndiceDeMorse y lo usamos para acceder a simbolosAscii; al resultado final (ascii) lo imprimimos con printf.

Código completo del traductor de código Morse en C

Ahora veamos el código completo; ya lo he explicado por partes. Todo está dividido en funciones que se invocan desde otros métodos o desde la función main.

#include <stdio.h> // Para printf
#include <string.h> // Para strcmp y strlen
#include <ctype.h> // Para toupper

#define LONGITUD_MENSAJE 500
/**
 * Traductor de código Morse en C
 *
 * Basado en https://parzibyte.me/blog/2019/10/20/traductor-codigo-morse-c/
 *
 * @author parzibyte
 * https://parzibyte.me/blog
 *
 * */// Código y signo iguales deben estar en el mismo índice
char *codigosMorse[] = {
        ".-", "-...", "-.-.", "-..",
        ".", "..-.", "--.", "....", "..",
        ".---", "-.-", ".-..", "--", "-.",
        "---", ".--.", "--.-", ".-.", "...",
        "-", "..-", "...-", ".--", "-..-",
        "-.--", "--..", "-----", ".----", "..---",
        "...--", "....-", ".....", "-....", "--...",
        "---..", "----.", ".-.-.-", "--..--", "---...",
        "..--..", ".----.", "-....-", "-..-.", ".--.-.",
        "-...-", ".-..-.", "-.-.--",};

char *simbolosAscii[] = {"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", "0", "1", "2",
                         "3", "4", "5", "6", "7",
                         "8", "9", ".", ",", ":",
                         "?", "'", "-", "/", "@",
                         "=", "\"", "!",};

const int NUMERO_CODIGOS = sizeof(codigosMorse) / sizeof(codigosMorse[0]);

int buscarIndiceDeMorse(char *codigo) {
    for (int x = 0; x < NUMERO_CODIGOS; x++) {
        if (strcmp(codigosMorse[x], codigo) == 0) {
            return x;
        }
    }
    return -1;
}

int buscarIndiceDeAscii(char signo) {
    // Convertir char a string
    char cadenaTemporal[2];
    cadenaTemporal[0] = signo;
    cadenaTemporal[1] = '\0';
    for (int x = 0; x < NUMERO_CODIGOS; x++) {
        if (strcmp(simbolosAscii[x], cadenaTemporal) == 0) {
            return x;
        }
    }
    return -1;
}

void demostrarCodificacionMorse() {
//    char mensaje[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,:?'-/@=\"!";
    char mensaje[LONGITUD_MENSAJE];
    printf("Mensaje a transformar en Morse: \n");
    fgets(mensaje, LONGITUD_MENSAJE, stdin);
    mensaje[strcspn(mensaje, "\r\n")] = 0; // Remover salto de línea
    // Recorremos la cadena y transformamos cada letra
    int i = 0;
    while (mensaje[i]) {
        // Convertir a mayúscula porque tenemos equivalencias solo para mayúsculas
        // y Morse no especifica minúscula
        char letraEnMayuscula = (char) toupper(mensaje[i]);
        int indice = buscarIndiceDeAscii(letraEnMayuscula);
        char *codigoMorse = codigosMorse[indice];
        // Aquí puedes hacer lo que gustes con el morse, yo simplemente lo imprimo
        printf("%s ", codigoMorse);
        i++;
    }
}

void demostrarDecodificacionMorse() {
//    char mensaje[] = ".- -... -.-. -.. . ..-. --. .... .. .--- -.- .-.. -- -. --- .--. --.- .-. ... - ..- ...- .-- -..- -.-- --.. ----- .---- ..--- ...-- ....- ..... -.... --... ---.. ----. .-.-.- --..-- ---... ..--.. .----. -....- -..-. .--.-. -...- .-..-. -.-.--";
    // Aquí define tu mensaje separado por espacios
    char mensaje[LONGITUD_MENSAJE];
    printf("Mensaje Morse a decodificar:\n");
    fgets(mensaje, LONGITUD_MENSAJE, stdin);
    mensaje[strcspn(mensaje, "\r\n")] = 0; // Remover salto de línea
    char delimitador[] = " ";
    // Separamos la cadena por espacios. Más información sobre strtok en https://parzibyte.me/blog/2018/11/13/separar-cadena-delimitadores-c-strtok/
    char *token = strtok(mensaje, delimitador);
    if (token != NULL) {
        while (token != NULL) {
            // Obtener cuál índice tiene este código
            int indice = buscarIndiceDeMorse(token);
            // Aquí puedes hacer lo que gustes con el ascii, yo simplemente lo imprimo
            char *ascii = simbolosAscii[indice];
            printf("%s", ascii);
            token = strtok(NULL, delimitador);
        }
    }
}

int main() {
    demostrarCodificacionMorse();
    printf("\n");
    demostrarDecodificacionMorse();
    return 0;
}

En mi caso lo he probado así:

Ejemplo de salida de código Morse a ASCII y viceversa en C

 

Conclusiones y notas

Recuerda que uso fgets porque es más seguro que scanf. Si quieres que esto funcione con cadenas más largas simplemente cambia el límite en LONGITUD_MENSAJE.

Por cierto, no estoy manejando el caso de que la función para buscar índices regrese -1; si quieres hacer el algoritmo más a prueba de errores simplemente haz esa comprobación.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.
parzibyte

Programador freelancer listo para trabajar contigo. Aplicaciones web, móviles y de escritorio. PHP, Java, Go, Python, JavaScript, Kotlin y más :) https://parzibyte.me/blog/software-creado-por-parzibyte/

Entradas recientes

Creador de credenciales web – Aplicación gratuita

Hoy te voy a presentar un creador de credenciales que acabo de programar y que…

1 semana hace

Desplegar PWA creada con Vue 3, Vite y SQLite3 en Apache

Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…

2 semanas hace

Arquitectura para wasm con Go, Vue 3, Pinia y Vite

En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…

2 semanas hace

Vue 3 y Vite: crear PWA (Progressive Web App)

En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…

2 semanas hace

Errores de Comlink y algunas soluciones

Al usar Comlink para trabajar con los workers usando JavaScript me han aparecido algunos errores…

2 semanas hace

Esperar promesa para inicializar Store de Pinia con Vue 3

En este artículo te voy a enseñar cómo usar un "top level await" esperando a…

2 semanas hace

Esta web usa cookies.