C Encryption - Caesar Cipher

Asked

Viewed 2,077 times

3

Good afternoon,

I’m developing a basic encryption code (Caesar’s cipher) in C.

I am using the logic of traversing 2 vectors: vetText and vetLetras, where the comparison of char and then replace it with 3 forward positions in the old Etras, but I’m not succeeding. The code compiles, but at the time of running is asking for text entries to be encrypted several times (entries larger than the vector size stipulated by me).

Code:

#include<stdio.h>   

int main (){

#define tamanhoTexto 4
#define qtdLetras 26

int i = 0, j = 0;
char vetTexto[tamanhoTexto];
char vetLetras[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' };

for(i=0; i<tamanhoTexto;i++){  //Lendo o texto a ser encriptado
scanf ("%c", &vetTexto[tamanhoTexto]);
}

for (i = 0; i < tamanhoTexto; i++){ //Varrendo os 2 vetores fazendo a busca de letras correspondentes
  for (j = 0; j < qtdLetras; j++){

      if(vetTexto[i] == vetLetras[j] && j+ 3 <qtdLetras){ //j+3(deslocamento) não pode sair do vetor letras

          vetTexto[i] = vetLetras[j+ 3];
      }else{ 

          j = j + 3;
          j = j - qtdLetras; //caso saia, faço a soma e tiro 26, pra voltar ao começo.
          vetTexto[i] = vetLetras[j];
      }
    }
  }
  for (i = 0; i < tamanhoTexto; i++){ //impressão do texto criptografado

  printf ("%c", vetTexto[i]);
}
  return 0;
}

I’ve seen some similar questions here on the forum, but they’re using a different logic and syntax than mine.

Being a little more objective: my doubts are:

  • Why the code doesn’t work?
  • The logic is correct?
  • There is a better way to apply this type of C encryption?

Thank you for your attention.

  • Hey, it’s all right. I already made this algorithm in php, if you want to take a look... https://github.com/flhorizonte/caesar-cipher-algorithm/blob/master/CifraCesar.php

2 answers

6


First problem

for(i=0; i<tamanhoTexto;i++){  //Lendo o texto a ser encriptado
scanf ("%c", &vetTexto[tamanhoTexto]);
}

Instead of &vetTexto[tamanhoTexto] was meant to be &vetTexto[i].

Second problem

            j = j + 3;
            j = j - qtdLetras; //caso saia, faço a soma e tiro 26, pra voltar ao começo.
            vetTexto[i] = vetLetras[j];

Do not change the variables that serve as the loop counter, being on the inside of it. This then ends up creating an infinite loop! Use this:

            int k = j + 3;
            if (k > qtdLetras) k = k - qtdLetras; //caso saia, faço a soma e tiro 26, pra voltar ao começo.
            vetTexto[i] = vetLetras[k];

Or simplifying it:

            vetTexto[i] = vetLetras[(j + 3) % qtdLetras];

Third problem

Note the if. He has to enter if the letters of the two loops are the same and he does not exceed the Z. Otherwise he enters the else. However, he should get into else only if it exceeds the Z, but still being the case of equal letters, but it enters the else also when the letters are different. The right one would then put so:

  if (vetTexto[i] == vetLetras[j]) {
      if (j + 3 < qtdLetras) {
          vetTexto[i] = vetLetras[j + 3];
      } else {
          vetTexto[i] = vetLetras[(j + 3) % qtdLetras];
      }
  }

First optimization

You do not need to declare the vector vetLetras. Just see that for any x between 0 and 25, vetLetras[x] has the value of 'A' + x. Thus, you can replace all occurrences of vetLetras[...] by this formula and thereby eliminate the vector vetLetras.

Second optimization

Once you can use the % qtdLetras when assigning a value to vetTexto[i], you will no longer need if internal, because with this operation of else, whether or not he’s over Z, he’ll be right.

Code conventions

To align code with language conventions, use LETRAS_MAIÚSCULAS for constants and put the #defines before the main. And also your code. I also suggest changing vetTexto to just texto.

Fourth problem

Your code must be like this:

for (i = 0; i < TAMANHO_TEXTO; i++) {
    for (j = 0; j < QTD_LETRAS; j++) {
        if (texto[i] == 'A' + j) texto[i] = 'A' + (j + 3) % QTD_LETRAS;
    }
}

You sweep the two vectors to make the substitution, but this if will only enter when j is equal to texto[i] - 'A'. In that case, you no longer need the inner loop, which is like this:

for (i = 0; i < TAMANHO_TEXTO; i++) {
    j = texto[i] - 'A';
    texto[i] = 'A' + (j + 3) % QTD_LETRAS;
}

And this in turn is reduced to this:

for (i = 0; i < TAMANHO_TEXTO; i++) {
    texto[i] = 'A' + (texto[i] - 'A' + 3) % QTD_LETRAS;
}

The variable j then becomes unnecessary.

Complete code

Your complete revised code looks like this:

#include <stdio.h>

#define TAMANHO_TEXTO 4
#define QTD_LETRAS 26

int main() {

    int i = 0;
    char texto[TAMANHO_TEXTO];

    for (i = 0; i < TAMANHO_TEXTO; i++) {
        scanf("%c", &texto[i]);
    }

    for (i = 0; i < TAMANHO_TEXTO; i++) {
        texto[i] = 'A' + (texto[i] - 'A' + 3) % QTD_LETRAS;
    }

    for (i = 0; i < TAMANHO_TEXTO; i++) {
        printf("%c", texto[i]);
    }

    return 0;
}

See here working on ideone. With the entrance ABXY, it produces the output DEAB.

  • 1

    Thank you so much for helping Victor! Could you ask me another question? I understood the final formula, but did not understand the logical step by step to get to the stretch of comparison and replacement, could explain me?

  • for (i = 0; i < TAMANHO_TEXTO; i++) { text[i] = 'A' + (text[i] - 'A' + 3) % QTD_LETRAS;

  • @H.Lima texto[i] is the letter. So, texto[i] - 'A' will be 0 to A, 1 to B, 2 to C, ... 25 to Z. Adding 3 to this, we have A going to 3, B to 4, ... Z to 28. Applying the % QTD_LETRAS, what will happen is that a number between 3 and 25 (which is from C to W) after the % 26 will look the same. Already with the X, Y and Z (which are 26, 27 and 28), will change to 0, 1 and 2. After all, the A + takes these numbers (A->3, ..., W->25, X->0, ..., Z->2) and transforms into (A->D, ... W->Z, X->A, ..., Z->C). This is attributed to the texto[i] then encrypting the text.

  • Now I understood, I had not realized that this excerpt was assigning numerical values to the letters, Thanks again!

-2

Voce needs the cc50 library to compile, you can find it here: https://github.com/GabrielRCL/CC50/tree/main/Semana%202/lib

use command to compile:

gcc -ggdb -std=c99 -Wall -Werror -Wformat=0 -o caesar caesar.c -lcc50 -lm

SCRIPT:

 #include <cc50.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h> //use this library to use "atoi()"
    
    //CIFRA DE CESAR - CRIPTOGRAFIA
    // FORMULA: Ci = ( Pi + k ) % 26
    // Ci = igésimo caractere criptografado
    // P = Frase para criptografar (string inserida)
    // Pi = igésimo caractere referente a String
    
    int
    main(int argc, char *argv[])    //char * = string
    {
        int k = atoi(argv[1]);  // k é o valor que o humano inserir no argumento transformado em inteiro
    
        char A = 'A';   // Int A = 65
        char a = 'a';   // Int a = 97
    
        printf("Insira o texto para criptografar: \n");
        string p = GetString();
    
    //   === [Criptografando] ===
        for (int i = 0, n = strlen(p); i < n; i++)
        {
            if (p[i] == 32) {
                //ESPAÇO - FIX BUG
                printf("%c", p[i]);
    
            } else if (p[i] < 97) {
                //LETRA MAIUSCULA
                int Pi = p[i] - ( (int)A - 1 ); //transformando para inteiro e subtraindo 64 para deixar o A = 1 / B = 2 / C = 3
                int Ci = ( ( Pi + k ) % 26 ) + ( (int)A - 1 );  //adicionando 64 para voltar aos valores normais de char A = 65 / B = 66 / C = 67
                printf("%c", Ci);
    
            } else {
                //LETRA MINUSCULA
                int Pi = p[i] - ( (int)a - 1 ); //transformando para inteiro e subtraindo 64 para deixar o a = 1 / b = 2 / c = 3
                int Ci = ( ( Pi + k ) % 26 ) + ( (int)a - 1 );  //adicionando 96 para voltar aos valores normais de char A = 97 / B = 98 / C = 99
                printf("%c", Ci);
            }
        }
        printf("\n");
    
    return 0;
    }

Browser other questions tagged

You are not signed in. Login or sign up in order to post.