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