Anteriormente vimos cómo implementar el algoritmo de cifrado de César en Python, ahora veremos cómo cifrar y descifrar una oración usando el cifrado César igualmente, pero en el lenguaje de programación C.
Implementar el algoritmo en C es un poco más complicado que en otros lenguajes, sobre todo por la manipulación de cadenas, pero eso no es un impedimento.
Veamos entonces cómo codificar el algoritmo de cifrado César en C.
Ya vimos cómo funciona el cifrado en términos generales. Ahora explicaré cómo usamos las funciones que provee C para alcanzar los resultados esperados, y cómo va el algoritmo general.
Recorremos la cadena letra por letra. A esa letra la convertimos a su representación entera, le sumamos las rotaciones necesarias y luego la convertimos de nuevo en letra; todo esto usando índices de cadenas y el código ASCII. Para decodificar o descifrar simplemente restamos en lugar de sumar.
Para saber si el carácter es una letra, usamos la función isalpha
; porque lo que no sea una letra no lo vamos a procesar. De igual manera, para saber si una letra es mayúscula usamos isupper
, lo necesitamos para saber cuál alfabeto usar.
Por otro lado, definimos algunas constantes como el máximo que puede tener la cadena, el código ascii de la a
y de la A
, la longitud del alfabeto y una función que calcula el módulo de un número y lo regresa de manera positiva.
Como necesitamos a ord
, usamos la función equivalente que vimos anteriormente. Otra cosa importante es la iteración de la cadena; usamos un simple while aumentando un contador.
Hablando del ciclo while, si el carácter no es una letra, utilizamos la palabra reservada continue
; la cual sirve para saltar a la siguiente iteración y no ejecutar el código que sigue.
El algoritmo como tal, funciona perfectamente. Tal vez sea complicada la parte en donde escaneamos la cadena, pero es porque fgets es mejor que scanf en cuanto a seguridad.
De todas maneras, la función trabaja por sí sola, la manera en la que le mandemos la cadena es cosa nuestra; en mi caso lo pongo de manera interactiva para que el usuario pueda probar fácilmente.
Aquí está todo el código, incluye las funciones necesarias para codificar una cadena en C utilizando el método César.
/*
Mi implementación del cifrado César en C
@author parzibyte
*/#include <stdio.h> // printf
#include <ctype.h> // isalpha, isupper
#include <string.h> // strcspn
#define LONGITUD_ALFABETO 26
#define INICIO_ALFABETO_MAYUSCULAS 65
#define INICIO_ALFABETO_MINUSCULAS 97
// Puedes ampliarlo si gustas, recuerda poner uno más aparte de la cantidad que
// escaneas
#define MAXIMA_LONGITUD_CADENA 5000
#define MOD(i, n) (i % n + n) % n // Calcular módulo positivo, gracias a
// https://stackoverflow.com/a/14997413/5032550
const char *alfabetoMinusculas = "abcdefghijklmnopqrstuvwxyz",
*alfabetoMayusculas = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// Recibe un mensaje a cifrar y un búfer en donde pondrá el resultado, así como
// las rotaciones que debe dar
void cifrar(char *mensaje, char *destino, int rotaciones);
// Recibe un mensaje a descifrar y un búfer en donde pondrá el resultado, así
// como las rotaciones que debe dar
void descifrar(char *mensaje, char *destino, int rotaciones);
// Obtener el valor entero de un carácter:
// https://parzibyte.me/blog/2018/12/11/ord-chr-c/
int ord(char c);
int main(void) {
// El original, el cifrado y luego el descifrado
char mensaje[MAXIMA_LONGITUD_CADENA], mensajeCifrado[MAXIMA_LONGITUD_CADENA],
mensajeDescifrado[MAXIMA_LONGITUD_CADENA];
printf("Escribe un mensaje para que lo cifre [Máximo %d caracteres]:\n",
MAXIMA_LONGITUD_CADENA - 1);
// Esto es para obtener el mensaje y evitar desbordamientos; se puede ignorar
fgets(mensaje, MAXIMA_LONGITUD_CADENA, stdin);
/*Quitar el salto de línea*/ mensaje[strcspn(mensaje, "\r\n")] = 0;
// ¿Cuántas rotaciones?
int rotaciones;
printf("Escribe el número de rotaciones que se darán a las letras:\n");
scanf("%d", &rotaciones);
// Ahora sí ciframos y descriframos
printf("El mensaje original es: %s\n", mensaje);
cifrar(mensaje, mensajeCifrado, rotaciones);
printf("El mensaje cifrado es: %s\n", mensajeCifrado);
descifrar(mensajeCifrado, mensajeDescifrado, rotaciones);
printf("El mensaje descifrado es: %s\n", mensajeDescifrado);
return 0;
}
void cifrar(char *mensaje, char *destino, int rotaciones) {
/*Recorrer cadena*/ int i = 0;
while (mensaje[i]) {
char caracterActual = mensaje[i];
int posicionOriginal = ord(caracterActual);
if (!isalpha(caracterActual)) {
destino[i] = caracterActual;
i++;
continue; // Ir a la siguiente iteración; por eso arriba aumentamos a i
}
if (isupper(caracterActual)) {
destino[i] =
alfabetoMayusculas[(posicionOriginal - INICIO_ALFABETO_MAYUSCULAS +
rotaciones) %
LONGITUD_ALFABETO];
} else {
destino[i] =
alfabetoMinusculas[(posicionOriginal - INICIO_ALFABETO_MINUSCULAS +
rotaciones) %
LONGITUD_ALFABETO];
}
i++;
}
}
void descifrar(char *mensaje, char *destino, int rotaciones) {
/*Recorrer cadena*/ int i = 0;
while (mensaje[i]) {
char caracterActual = mensaje[i];
int posicionOriginal = ord(caracterActual);
if (!isalpha(caracterActual)) {
destino[i] = caracterActual;
i++;
continue; // Ir a la siguiente iteración; por eso arriba aumentamos a i
}
if (isupper(caracterActual)) {
destino[i] = alfabetoMayusculas[MOD(
posicionOriginal - INICIO_ALFABETO_MAYUSCULAS - rotaciones,
LONGITUD_ALFABETO)];
} else {
destino[i] = alfabetoMinusculas[MOD(
posicionOriginal - INICIO_ALFABETO_MINUSCULAS - rotaciones,
LONGITUD_ALFABETO)];
}
i++;
}
}
int ord(char c) { return (int)c; }
En el método main puse un ejemplo de uso. Espero que sea claro.
Si quieres cifrar, reserva 2 búfers o cadenas del mismo tamaño: una que tiene el mensaje original y otra en donde será puesto el mensaje cifrado.
En caso de que quieras descifrar, igualmente reserva 2 búfers del mismo tamaño. En uno pon el mensaje cifrado, y en el otro se pondrá el mensaje descifrado.
Todo esto, sin importar si cifras o no, está determinado por el número de rotaciones. Recuerda que si, por ejemplo, cifras con 3 rotaciones, debes hacer la operación inversa con el mismo número.
Hoy te voy a presentar un creador de credenciales que acabo de programar y que…
Ya te enseñé cómo convertir una aplicación web de Vue 3 en una PWA. Al…
En este artículo voy a documentar la arquitectura que yo utilizo al trabajar con WebAssembly…
En un artículo anterior te enseñé a crear un PWA. Al final, cualquier aplicación que…
Al usar Comlink para trabajar con los workers usando JavaScript me han aparecido algunos errores…
En este artículo te voy a enseñar cómo usar un "top level await" esperando a…
Esta web usa cookies.
Ver comentarios