Cifrario di Cesare in C++, Rust, Python, Java

Un esercizio decisamente classico per i novelli della programmazione. Vediamo un semplice cifrario di Cesare che funziona nel seguente modo: viene inserito un testo arbitrario, viene inserita una chiave numerica, si traspone il testo lettera per lettera di tante posizioni alfabetiche secondo la chiave e si fornisce in output il testo crittografato. Per completezza sviluppiamo una soluzione in diversi linguaggi, confrontando così le potenzialità di ognuno.

Versione C++

Presentiamo il nostro cifrario forse in modo un po’ più complesso, aggiungendo un menù per scegliere l’operazione da effettuare, se cifrare o decifrare un testo. In questo modo il main diventa semplicemente un loop per la scelta dell’operazione mentre alle due funzioni cifra/decifra è affidato il compito specifico. L’alunno che necessita dell’esercizio in modo più semplice può limitarsi al codice di una delle due funzioni cifra/decifra.

L’algoritmo di suo è piuttosto semplice. Le funzioni in realtà sono speculari: una aggiunge la chiave, l’altra lo sottrae per riottenere il testo in chiaro. L’unico dettaglio che forse è il caso notare sono le diciture:

    cin.ignore();
    getline(cin, testoInChiaro);

Le stringhe C++ infatti non ammettono gli spazi se lette da cin > qualcosa, mentre con questo stratagemma, possiamo inserire un testo dotato di lettere, numeri, punteggiatura varia e spazi!

#include <iostream>
#include <string>

using namespace std;

void cifra()
{
    string testoInChiaro;
    string testoCifrato;
    int chiave;

    cout << "Scegli la chiave (intero +/- 25 max)" ;
    do 
    {
        cin >> chiave;
    }
    while (chiave < -26 || chiave > 26);
    
    cout << "Inserisci il testo da crittografare" << endl;
    cout << ": ";
    cin.ignore();
    getline(cin, testoInChiaro);

    for (int i = 0; i < testoInChiaro.length(); i++)
    {
            testoCifrato += testoInChiaro[i] + chiave;
    } 

    cout << "Testo crittografato" << endl;
    cout << ": ";
    cout << testoCifrato << endl;
}


void decifra()
{
    string testoInChiaro;
    string testoCifrato;
    int chiave;

    cout << "Indica la chiave scelta precedentemente (intero +/- 25 max)" ;
    do 
    {
        cin >> chiave;
    }
    while (chiave < -26 || chiave > 26);
    
    cout << "Inserisci il testo da decifrare" << endl;
    cout << ": ";
    cin.ignore();
    getline(cin, testoCifrato);

    for (int i = 0; i < testoCifrato.length(); i++)
    {
            testoInChiaro += testoCifrato[i] - chiave;
    } 

    cout << "Testo in chiaro" << endl;
    cout << ": ";
    cout << testoInChiaro << endl;
}

int main()
{
    int scelta = 0;

    cout << "|-------------------------|" << endl;
    cout << "|   CIFRARIO DI CESARE    |" << endl;
    cout << "|-------------------------|" << endl;
    cout << endl;

    do 
    {
        cout << "Cosa vuoi fare? "<<endl;
        cout << "1 - Cifrare " << endl;
        cout << "2 - Decifrare " << endl;
        cout << "0 - Uscire " << endl;
        cin >> scelta;

        switch (scelta)
        {
        case 1:
            cifra();
            break;

        case 2:
            decifra();
            break;

        case 0:
            return 0;
            break;
        
        default:
            //non faccio nulla richiedo l'input
            break;
        }

    }
    while(scelta != 0);

    return 0;
}

Versione Rust

Con Rust implementiamo il medesimo algoritmo ed interfaccia del C++ ma i due linguaggi sono profondamente diversi. Per certi versi il Rust sembra avere un approccio più a basso livello del fratellone. Gli input e i cicli do-while apparentemente hanno una sintassi più complessa, idem il cast lettera/numero per l’aggiunta della chiave.

use std::io;

fn cifra()
{
    let mut testoCifrato = String::new();
    let mut chiave :i32;

    loop
    {
        println!("Scegli la chiave (intero +/- 25 max)");
        let mut input = String::new();
        io::stdin().read_line(&mut input);
        chiave = input.trim().parse().expect("Chiave non valida");
        if chiave > -26 || chiave < 26
        {
            break;
        }
    }

    println!("Inserisci il testo da crittografare");
    let mut testoInChiaro = String::new();
    io::stdin().read_line(&mut testoInChiaro);

    for i in 0..testoInChiaro.len() -1
    {
        let carattere = testoInChiaro.chars().nth(i).unwrap();
        let carattere_trasp= carattere as u8 + chiave as u8;
        testoCifrato.push(char::from(carattere_trasp));
    }

    println!("Testo crittografato");
    println!(": {}",testoCifrato);
}

fn decifra()
{
    let mut testoInChiaro = String::new();
    let mut chiave :i32;

    loop
    {
        println!("Inserisci la chiave in tuo possesso (intero +/- 25 max)");
        let mut input = String::new();
        io::stdin().read_line(&mut input);
        chiave = input.trim().parse().expect("Chiave non valida");
        if chiave > -26 || chiave < 26
        {
            break;
        }
    }

    println!("Inserisci il testo da decifare");
    let mut testoCifrato = String::new();
    io::stdin().read_line(&mut testoCifrato);

    for i in 0..testoCifrato.len() -1
    {
        let carattere = testoCifrato.chars().nth(i).unwrap();
        let carattere_trasp= carattere as u8 - chiave as u8;
        testoInChiaro.push(char::from(carattere_trasp));
    }

    println!("Testo decifrato");
    println!(": {}",testoInChiaro);
}

fn main()
{
    println!("|-------------------------|");
    println!("|   CIFRARIO DI CESARE    |");
    println!("|-------------------------|");
    println!();

    let mut scelta = 0;

    loop
    {
        println!("Cosa vuoi fare? ");
        println!("1 - Cifrare ");
        println!("2 - Decifrare ");
        println!("0 - Uscire ");

        let mut input = String::new();
        io::stdin().read_line(&mut input);
        scelta = input.trim().parse()
            .expect("Non hai inserito un numero valido");

        match scelta
        {
            1=>cifra(),
            2=>decifra(),
            0=>return,
            _=>println!("Scelta non valida"),
        }

        if scelta == 0 { break; }
    }
}

Versione Python

La versione Python del medesimo algoritmo ha implementazione molto semplice, forse di gran lunga più semplice di C++ e Rust.


def cifra():
    while True:
        chiave=eval(input("Inserisci la chiave (intero +/- 25 max): "))
        if chiave >= -26 and chiave <= 26:
            break
    testoInChiaro = input("Inserisci il testo da crittografare")
    testoCifrato = ""
    for lettera in testoInChiaro:
        testoCifrato += chr(ord(lettera)+chiave)
    
    print("Testo cifrato")
    print(": ", testoCifrato)

def decifra():  
    while True:
        chiave=eval(input("Inserisci la chiave (intero +/- 25 max): "))
        if chiave >= -26 and chiave <= 26:
            break

    testoCifrato = input("Inserisci il testo da crittografare")
    testoInChiaro = ""
    for lettera in testoCifrato:
        testoInChiaro += chr(ord(lettera)-chiave)
            
    print("Testo decifrato")
    print(": ",testoInChiaro)

    
if __name__ == "__main__":
    print("|-------------------------|\n")
    print("|   CIFRARIO DI CESARE    |\n")
    print("|-------------------------|\n")

    while True:
        print("Cosa vuoi fare? ")
        print("1 - Cifrare ")
        print("2 - Decifrare ")
        print("0 - Uscire ")
        scelta= eval(input())
        
        match scelta:
            case 1:
                cifra()
            case 2:
                decifra()
            case 0:
                exit()
            case _:
                print("Errore")
        

Versione Java

TO DO

import java.util.Scanner;

public class Cifrario
{
    public static void cifra()
    {
        int chiave;
        String testoCifrato = new String();
        do {
            System.out.println("Inserisci la chiave in tuo possesso (intero +/- 25 max)");
            Scanner s = new Scanner(System.in);
            chiave = s.nextInt();
        }
        while (chiave < -26 || chiave > 26);

        System.out.println("Inserisci il testo da crittografare");
        Scanner s = new Scanner(System.in);
        String testo = s.nextLine();

        for (int i = 0; i < testo.length(); i++)
        {
            char lettera = testo.charAt(i);
            //testoCifrato += lettera + (char)chiave; NO usa vettore di char e poi riconverti in new String
        }

        System.out.println(testoCifrato);
    }

    public static void decifra()
    {

    }

    public static void main(String [] args)
    {
        System.out.println("|-------------------------|");
        System.out.println("|   CIFRARIO DI CESARE    |");
        System.out.println("|-------------------------|");
        System.out.println();
        int scelta;

        while (true)
        {
            System.out.println("Cosa vuoi fare? ");
            System.out.println("1 - Cifrare ");
            System.out.println("2 - Decifrare ");
            System.out.println("0 - Uscire ");

            do
            {
                Scanner s = new Scanner(System.in);
                scelta = s.nextInt();
            }
            while(scelta < 0 && scelta > 2);

            switch (scelta)
            {
                case 1:
                    cifra();
                    break;

                case 2:
                    decifra();
                    break;

                case 0:
                    return;
            }

        }

    }
}

Ultima modifica 18 Aprile 2023