DEV Community

Matheus 🇧🇷
Matheus 🇧🇷

Posted on

CS50 : S2 | Cifra de César - Parte 1

Cifra de César

Em criptografia, a Cifra de César, também conhecida como cifra de troca, código de César ou troca de César, é uma das mais simples e conhecidas técnicas de criptografia. É um tipo de cifra de substituição na qual cada letra do texto é substituída por outra, que se apresenta no alfabeto abaixo dela um número fixo de vezes. Por exemplo, com uma troca de três posições, A seria substituído por D, B se tornaria E, e assim por diante. O nome do método é em homenagem a Júlio César, que o usou para se comunicar com os seus generais.
-- Wikipedia

Nestes problemas que seguem, o algoritmo de César criptografa mensagens rotacionando as letras de acordo com k posições. Veremos abaixo, nas etapas como transferimos aquela fórmula matemática para o nosso código.

Quebrando o código

  • Pseudocódigo
    1) Receber do usuário uma chave que corresponderá em quantas posições vai girar
    2) Receber do usuário uma mensagem
    3) Iterar sobre cada letra da mensagem

    • Se for maiúscula, preservar, e trocar o caracter de acordo com a chave.
    • Se for minúscula, preservar, e trocar o caracter de acordo com a chave
    • Se não for uma letra, preservar o caracter da mensagem original 4) Imprimir mensagem criptografada em tela
  • Código em C

#include <cs50.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h>  void stringCipher(string text, int key); int main(int argc, string argv[]) { if(argc != 2) { printf("Usage: ./caesar key\n"); return 1; } int key = atoi(argv[1]); string plaintext = get_string("plaintext: "); stringCipher(plaintext, key); } void stringCipher(string text, int key) { char cypher[strlen(text)]; string lowerAlphabet = "abcdefghijklmnopqrstuvwxyz"; string upperAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; for(int i = 0; i < strlen(text); i++) { if(isalpha(text[i])) { if(islower(text[i])) { int position = text[i] - 97; int c = (position + key) % 26; cypher[i] = lowerAlphabet[c]; } else if(isupper(text[i])) { int position = text[i] - 65; int c = (position + key) % 26; cypher[i] = upperAlphabet[c]; } } else { cypher[i] = text[i]; } } printf("ciphertext: %s\n", cypher); } 
Enter fullscreen mode Exit fullscreen mode

Recebendo a Chave do usuário

Na aula 2 vimos sobre a Interface de Linha de Comando e como podemos receber argumentos do usuário através do argv[].

Sabendo-se que toda informação que vem pelo argv[] é do tipo string (por conta do cs50.h). Precisamos converter para o tipo int, para que seja um número, e assim, usarmos na fórmula matemática. Para isto, usaremos a função atoi() que faz parte da biblioteca stdlib.h.

Assim, quando o usuário entrar com um argumento, esse número não será uma string, e sim um número inteiro.

int key = atoi(argv[1]);

Função para a Criptografia

Agora vamos falar sobre a função que faz a mágica acontecer.

void stringCipher(string text, int key) { char cypher[strlen(text)]; string lowerAlphabet = "abcdefghijklmnopqrstuvwxyz"; string upperAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; for(int i = 0; i < strlen(text); i++) { if(isalpha(text[i])) { if(islower(text[i])) { int position = text[i] - 97; int c = (position + key) % 26; cypher[i] = lowerAlphabet[c]; } else if(isupper(text[i])) { int position = text[i] - 65; int c = (position + key) % 26; cypher[i] = upperAlphabet[c]; } } else { cypher[i] = text[i]; } } printf("ciphertext: %s\n", cypher); } 
Enter fullscreen mode Exit fullscreen mode

1) Criar uma array de caracteres.

O char cypher[strlen(text)] veio para fazer isso. Em C, temos que especificar o tamanho da array que vamos criar, como o tamanho pode ser variável, a depender de qual mensagem o usuário vai colocar, eu optei para que seja criado sempre com o mesmo tamanho da mensagem do usuário.

Dessa maneira, faz-se o uso do strlen() que faz parte da biblioteca string.h. Ela calcula o tamanho de uma string, e uma string é o que? Uma string é uma array de caracteres.
E então, seja qual foi o tamanho da string inicial, traduzirá para essa array de caracteres onde eu vou armazenar as letras criptografadas.

2) Uma string é um array de caracteres

Partindo desse pensamento, criei duas strings, uma para o abcdário minúsculo, e outro para maiúsculo. No enunciado, o problema levanta a ideia da letra A estar na posição 0, a letra B estar na posição 1, e por aí vai.

Então quando eu tenho:
lowerAlphabet[0] eu tenho acesso ao valor a
lowerAlphabet[1] eu tenho acesso ao valor b

Conseguindo assim replicar o enunciado do problema em questão.

3) Iterando e verificando se é uma letra do alfabeto

Começamos iterando sobre toda o tamanho da mensagem original.

for(int i = 0; i < strlen(text); i++) { //todo } 
Enter fullscreen mode Exit fullscreen mode

E agora usamos mais uma função, que a doc do cs50 fornece, isalpha() que pertence a biblioteca ctype.h. Dessa maneira, conseguiremos verificar posição-a-posição, se é um caracter alfabético ou não.

  • Se for, aí começa o processo de encriptar.
  • Se não, replica esses caracteres para a mensagem cifrada como são originalmente.

4) A lógica por trás e como ASCII é necessário

De novo, como no problema de readability, que já fiz uma explicação sobre, precisaremos da tabela de ASCII para descobrir a localização dos caracteres.

ASCII Chart

A lógica para letras maiúsculas é praticamente a mesma para a letras minúsculas, por isso falarei só das letras minúsculas.

Seguimos,

if(islower(text[i])) { //bloco de comandos } 
Enter fullscreen mode Exit fullscreen mode

Usamos a função islower(), da biblioteca ctype.h, em nossa condicional. Caso seja verdadeiro, executurá esse bloco de comandos

 int position = text[i] - 97; int c = (position + key) % 26; cypher[i] = lowerAlphabet[c]; 
Enter fullscreen mode Exit fullscreen mode

Vamos por partes agora, de acordo com a tabela ASCII a letra a corresponde ao valor 97.
Queremos que ela venha valer 0. Por quê?
Porque se ela valer 0, eu posso dizer que a letra a está na posição 0. Assim, para qualquer chave eu posso andar sobre a minha string lowerAlphabet e trocar o valor, assm ter a minha mensagem encriptada.

  • Então primeiro eu quero a posição:

int position = text[i] - 97;
Fazer uma subtração assim, vai forçar o C a transformar esse char na sua int correspondente

int position = 'a' - 97; --------------- char: a -> int: 97
int position = 0

E assim valerá para todos os caracteres que corresponderem ao abcedário de a a z.

  • Aplicar a fórmula da criptografia de acordo com o exercício proposto

int c = (position + key) % 26;

Pegamos a posição da letra da mensagem original e somamos com a quantidade de casas que vai pular, pegando assim o seu resto ao fazer a divisão por 26.

Então por exemplo:

- Letra a + key 1 - Char: a => Int: 97 - position = 97 - 97 => position = 0 - c = (position + key) % 26 => c = (0 + 1) % 26 => c = 1 - lowerAlphabet[1] = b - Letra z + key 16 - Char: z => Int: 122 - position = 122 - 97 => position = 25 - c = (position + key) % 26 => c = (25 + 16) % 26 => c = 15 - lowerAlphabet[15] = p 
Enter fullscreen mode Exit fullscreen mode
  • Armazenando esse valor em nossa array criptografada

cypher[i] = lowerAlphabet[c];

Seguindo a letra encontrada, armazena a nova letra na posição indicada.

E assim, ao terminar a iteração em toda a extensão da string da mensagem original, podemos imprimir a nova mensagem, agora criptograda atráves da nossa array cypher[] de chars.

Atráves da,
printf("ciphertext: %s\n", cypher);

E as letras maiúsculas?

Seguindo a mesma lógica acima, olhe a tabela ASCII e verifique, o que você mudaria?
Depois confira no código e repita os passos acima, a lógica é a mesma.

Não existe só uma maneira de resolver, nem a melhor. A melhor maneira, é aquela que você entende e onde você consegue resolver o problema da questão envolvida.

final image

Conclusão

Eu ia comentar sobre o exercício da substituição nesse mesmo post, mas vai ficar muito longo.

Ficará para uma parte 2.

Espero que este post tenha te ajudado a entender mais sobre essa manipulação de arrays, e como a biblioteca fornecida pelo docs do cs50 é importante.

Te vejo na próxima, e não se esqueça de me seguir no twitter.

Top comments (0)