Domanda Risolto C++ Polibio crittografia

Stato
Discussione chiusa ad ulteriori risposte.

MisterMPG

Utente Iron
21 Novembre 2020
21
3
0
9
Ultima modifica:
Ciao a tutti mi aiutate a fare un programma in C++ che esegue quello che fa il metodo crittografico di Polibio?
Grazie a tutti.
Messaggio unito automaticamente:

So che è possibile rappresentare il metodo con un array a due dimensioni pero' non posso farlo perchè non è un argomento trattato a scuola, non so realmente come rappresentarlo senza tale array.....
 

Allegati

  • Polibio.jpg
    Polibio.jpg
    478.7 KB · Visualizzazioni: 166
Puoi implementarlo su un array monodimensionale che mappa ogni carattere al rispettivo numero
C:
int polibio[] = {
    11,  // a
    12,  // b
    13,  // c
    14,  // d
    15,  // e
    21,  // f
         // ...
};
e codificare ogni carattere della stringa in un numero facendo polibio[c - 'a']; nel caso c sia una minuscola.

In alternativa, puoi scordarti di usare gli array e calcolare gli indici algebricamente. Una volta che converti ogni carattere in un numero da 0 a 25 (sottraendo 'a' oppure 'A', come spiegato sopra), l'indice di riga lo ottieni con una divisione per 5 e l'indice di riga lo ottieni con un modulo 5.

Inizia a scrivere un po' di codice e poi ne riparliamo.
 
Guarda ti giuro sono negato per queste cose ho torvato questo online ma faccio fatica a capirlo, anche per esempio ceil non l'ho mai usato, poi per 'a' dobbiamo pensare al codice asci di a o all'a che c'è nella tabella?.
Francamente non so farlo, è inutile che ci giro intorno, se puoi aiutarmi spiegandomelo te ne sono grato.

Codice:
#include <cmath>
#include <iostream>
using namespace std;
void LetterToNumber(string str) {
   int R, C;
   for (int i = 0; str[i]; i++) {
      R = ceil((str[i] - 'a') / 5) + 1;
      C = ((str[i] - 'a') % 5) + 1;
      if (str[i] == 'k') {
         R = R - 1;
         C = 5 - C + 1;
      }
      else if (str[i] >= 'j') {
         if (C == 1) {
            C = 6;
            R = R - 1;
         }
         C = C - 1;
      }
      cout<<R<<C;
   }
   cout << endl;
}
int main() {
   string str = "k";
   cout<<"The numeric encryption of string '"<<str<<"' is : ";
   LetterToNumber(str);
   return 0;
}
 
Secondo me con il giusto impegno ti saresti almeno avvicinato alla soluzione giusta. Facciamo che ti spiego questo codice che ho scritto io:
C++:
#include <iostream>
#include <string>
using namespace std;

int encode_char(char c) {
  int square[] = {
      11, 12, 13, 14, 15,  // a b c d e
      21, 22, 23, 24, 25,  // f g h i j
      31, 31, 32, 33, 34, 35,  // k l m n o p
      41, 42, 43, 44, 45,  // q r s t u
      51, 52, 53, 54, 55   // v w x y z
  };

  if ('a' <= c && c <= 'z')
    return square[c - 'a'];
  else if ('A' <= c && c <= 'Z')
    return square[c - 'A'];
  return 0;  // carattere non codificabile
}

int main() {
  string text;
  cout << "Inserisci una parola: ";
  cin >> text;

  for (char c : text)
    cout << encode_char(c);
  cout << endl;

  // senza usare il for each
  // for (int i = 0; i < text.length(); i++)
  //   cout << encode_char(text[i]);
  // cout << endl;

  return 0;
}

Partiamo dal main. Chiedo all'utente di inserire del testo senza spazi (e.g., AttenzioneAgliScogli) e per ogni carattere nella stringa in input eseguo la funzione encode_char. Credo sia tutto chiaro tranne forse per il for each, che magari non hai studiato, ma che io ti ho proposto (commentato) anche sotto forma di for classico.

Cosa fa la funzione encode_char? Controlla se il carattere è minuscolo (if) o maiuscolo (else if). Un carattere non è altro che un numero (ASCII table), quindi: facendo A-A=0, B-A=1, C-A=2 e sebbene A (maiuscolo) è diverso da a (minuscolo), vale comunque a-a=0, b-a=1, etc... Di conseguenza, con c - 'a' (if) o con c - 'A' (else if) stiamo semplicemente convertendo il carattere in un numero che va da 0 (a e A) a 25 (z e Z). Questo numero da 0 a 25 lo utilizziamo come indice per l'array square, che contiene il quadrato di Polibio linearizzato. Esempio:
Codice:
'A' - 'A'  => 0
square[0]  => 11

'z' - 'a'  => 25
square[25] => 55

Ovviamente dobbiamo ricordarci che K e Q sono entrambe 31, ovvero che all'indice K-A=10 e all'indice Q-A=16 dell'array dobbiamo inserire il numero 31.
 
@St3ve forse mi sono perso qualcosa, ma non mi sembra sia corretto dall'array.

Provandolo:
Codice:
Inserisci una parola: kq
3141

EDIT:

Comunque mi sfugge perchè in tabella abbiano codificato con il 31 sia k che q. In caso di decodifica, come torni indietro? "kuadro" == "quadro"...
 
  • Grazie
Reazioni: St3ve
Ultima modifica:
Caspita sei bravissimo niente da dire, mi inchino umilmente....
Purtroppo non capisco ancora bene..
QUesta parte:
int encode_char(char c) ???
{
int square[] = ????
{
11, 12, 13, 14, 15, // a b c d e
21, 22, 23, 24, 25, // f g h i j
31, 31, 32, 33, 34, 35, // k l m n o p
41, 42, 43, 44, 45, // q r s t u
51, 52, 53, 54, 55 // v w x y z
};

if ('a' <= c && c <= 'z') ????
return square[c - 'a']; ????
else if ('A' <= c && c <= 'Z') ?????
return square[c - 'A']; ??????

Non riesco a capire la funzione dell [] dopo int square d il meccanismo che porta encode_char a controllare miuscole e maiuscole..
Square non l'ho mai usato non lo conosco....
INoltre:
"Un carattere non è altro che un numero (ASCII table), quindi: facendo A-A=0, B-A=1, C-A=2 e sebbene A (maiuscolo) è diverso da a (minuscolo), vale comunque a-a=0, b-a=1, etc... Di conseguenza, con c - 'a' (if) o con c - 'A' (else if) stiamo semplicemente convertendo il carattere in un numero che va da 0 (a e A) a 25 (z e Z). Questo numero da 0 a 25 lo utilizziamo come indice per l'array square, che contiene il quadrato di Polibio linearizzato."
 
Ultima modifica:
@St3ve forse mi sono perso qualcosa, ma non mi sembra sia corretto dall'array.
Oh giusto, come si vede dal commento ho unito K e L invece di K e Q. Ovviamente l'array corretto è
C:
int square[] = {                          
    11, 12, 13, 14, 15,  // a b c d e     
    21, 22, 23, 24, 25,  // f g h i j     
    31, 32, 33, 34, 35,  // k l m n o     
    41, 31, 42, 43, 44, 45,  // p q r s t u
    51, 52, 53, 54, 55   // v w x y z     
};

Non riesco a capire la funzione dell [] dopo int square d il meccanismo che porta encode_char a controllare miuscole e maiuscole..
Hai studiato gli array e non hai studiato gli array bidimensionali, oppure non hai proprio mai fatto gli array e volevi una soluzione che non li usasse? Se ti disturba il fatto che non ho specificato nessuna dimensione, puoi tranquillamente scrivere int square[26] = { /* contenuto */ };.

es C-A=2 ?? Se guardo la teblla ascii a=65, tu intendo la terza lettera dell'alfabeto?
Quando si indicizzano gli array (e in generale quando si parla di informatica) si inizia a contare da zero: A=0, B=1, C=2, D=3, ..., Z=25. Il primo indice è zero e il ventiseiesimo indice è 25.

if ('a' <= c && c <= 'z')
Guardando la tabella ASCII la a (minuscola) corrisponde al numero 97 e la z (minuscola) è 122. Le lettere sono disposte in ordine, quindi i valori da 97 a 122 sono tutte e 26 le lettere minuscole. Allo stesso modo, guardando la tabella ASCII, la A (maiuscola) corrisponde a 65 e la Z (maiuscola) è 90 e tutti i valori da 65 a 90 sono tutte e 26 le lettere maiuscole. Avrei potuto scrivere if (97 <= c && c <= 122), ma ho preferito usare direttamente i char 'a' e 'z' per rendere più chiaro il significato della condizione.

Quando faccio c - 'a' oppure c - 'A' per calcolare l'indice, è come se stessi facendo c - 97 oppure c - 65. Sto semplicemente convertendo la sequenza da 97 a 122 e la sequenza da 65 a 90 nella sequenza da 0 a 25.

Comunque mi sfugge perchè in tabella abbiano codificato con il 31 sia k che q. In caso di decodifica, come torni indietro? "kuadro" == "quadro"...
È Polibio che, essendo un cifrario vecchio e usato "a mano" sceglie di codificare due lettere con lo stesso simbolo. Qualcosa di simile avviene anche con Playfair: è bello avere un quadrato, ma purtroppo le lettere dell'alfabeto sono 26. Generalmente si dice K=Q, I=J oppure C=K almeno leggendo la frase capisci comunque il significato (si pronunciano in modo simile).
 
Ultima modifica:
SCusami ma l'uso della variabile char usata per 'a' fino a 'z' o da 'A' sino a 'Z' identifica quindi il codice ascii della lettera ? che poi sia 97 a 122 o la sequenza da 65 a 90 in pratica è come avere da 0 a 25 elementi dell'array giustamente , ho capito bene?
Ti ringrazio molto.
Messaggio unito automaticamente:

Ti chiedo anche non si puo' scrivere cosi' il codice :

Codice:
       #include <iostream>
#include <string>
using namespace std;

int encode_char(char c) {
int square[] = {
    11, 12, 13, 14, 15,  // a b c d e    
    21, 22, 23, 24, 25,  // f g h i j    
    31, 32, 33, 34, 35,  // k l m n o    
    41, 31, 42, 43, 44, 45,  // p q r s t u
    51, 52, 53, 54, 55   // v w x y z

};

if ('a' <= c && c <= 'z')
return square[c - 'a'];
else if ('A' <= c && c <= 'Z')
return square[c - 'A'];
return 0; // carattere non codificabile
}

int main() {
char c;                                             // anziche' string text;
cout << "Inserisci una parola: ";
cin >> c;                                        // anzichè  cin>> text

for (char c )                            //  anzichè (char c : text)
cout << encode_char(c);
cout << endl;

// senza usare il for each
// for (int i = 0; i < text.length(); i++)
// cout << encode_char(text[i]);
// cout << endl;

return 0;
}
Messaggio unito automaticamente:

INoltre un problema.... se voglio mettere la frase con gli spazi "Attenzione agli scogli"
Attenzione agli scogli
11444415345524353415 11223224 431335223224
Cosa devo modficare?
Perchè scrivendo il codice sopra viene solo 11444415345524353415
 
Mi sembra basilare quanto chiedi... ho la sensazione non ti siano chiari concetti alla base.

C:
char c;                                             // anziche' string text;
cout << "Inserisci una parola: ";
cin >> c;                                        // anzichè  cin>> text

for (char c )                            //  anzichè (char c : text)

char rappresenta un carattere, tu devi memorizzare una parola. Devi quindi usare un insieme di caratteri, e quindi una string.
Il for che ha scritto St3v3 è un foreach, non ha scelto lui come scriverlo. La keyword usata è disponibile da C++11 (se non erro) https://en.cppreference.com/w/cpp/language/range-for

INoltre un problema.... se voglio mettere la frase con gli spazi "Attenzione agli scogli"
Attenzione agli scogli
11444415345524353415 11223224 431335223224
Cosa devo modficare?
Perchè scrivendo il codice sopra viene solo 11444415345524353415

Voglio cercare di condurti senza scrivertelo.
Guarda il codice:

C++:
  for (char c : text)
    cout << encode_char(c);
  cout << endl;

Devi solo verificare se c è un carattere e stampare uno spazio (senza richiamare encode_char).
 
  • Mi piace
Reazioni: 0xbro

Ho scritto l'altro codice cosi' perchè vedevo che avevo gli stessi risultati anche se ho capito la differenza tra char e string.
Per il discorso stampare spazio ho trovato online e mai studiato questo, è quello che intendevi?

"



How do you check if a character is a space in C++?
The isspace() function in C++ checks if the given character is a whitespace character or not.
...
C++ isspace()
  1. space (0x20, ' ')
  2. form feed (0x0c, '\f')
  3. line feed (0x0a, '\n')
  4. carriage return (0x0d, '\r')
  5. horizontal tab (0x09, '\t')
  6. vertical tab (0x0b, '\v')
"

e quindi mettere tipo

if (isspace(c))

Pero' ripeto non l'ho mai studiato...
 
Prova a pensare tu alla soluzione, senza cercare tutto online.
Comunque non puoi aspettarti di fare ogni singola cosa a scuola, sarà sempre tutto in mano tua. ;)

C++:
  getline(cin, text);

  for (char c : text) {
    if( c != ' ')
        cout << encode_char(c);
    else 
        cout << " ";
  }

Con il getline leggi sino all'inserimento del "new line" (invio).
Se vuoi gestire anche tab, new line etc. puoi usare isspace, come hai proposto.
 
Ultima modifica:
Ho provato a sistemare cosi' (evitando il foreach) non mi viene la parte iniziale se scrivo "Attenzione agli scogli"..
11223224 431335223224 anzichè 11444415345524353415 11223224 431335223224
Cosa ho sbagliato?

Codice:
#include <iostream>
#include <string>
using namespace std;

int controlchar(char c)

{
  int array[]

   {
    11, 12, 13, 14, 15,  // a b c d e 
    21, 22, 23, 24, 25,  // f g h i j 
    31, 32, 33, 34, 35,  // k l m n o 
    41, 31, 42, 43, 44, 45,  // p q r s t u
    51, 52, 53, 54, 55   // v w x y z
  };

  if ('a' <= c && c <= 'z')
    return array[c - 'a'];
  else if ('A' <= c && c <= 'Z')
    return array[c - 'A'];
  return 0;  // carattere non codificabile
}

int main() {
  string text;
  cout << "Inserisci una parola: ";
  cin >> text;
  getline(cin, text);


   for (int i = 0; i < text.length(); i++) {
     if(text[i] != ' ')
       cout << controlchar(text[i]);
  else cout << " "; 
}
  cout << endl;

  return 0;
}
Messaggio unito automaticamente:

Ma anche se provo cosi' non viene giusta:

Codice:
#include <iostream>
#include <string>
using namespace std;

int controlchar(char c)

{
  int array[]
 
   {
    11, 12, 13, 14, 15,  // a b c d e     
    21, 22, 23, 24, 25,  // f g h i j     
    31, 32, 33, 34, 35,  // k l m n o     
    41, 31, 42, 43, 44, 45,  // p q r s t u  
    51, 52, 53, 54, 55   // v w x y z
  };

  if ('a' <= c && c <= 'z')
    return array[c - 'a'];
  else if ('A' <= c && c <= 'Z')
    return array[c - 'A'];
  return 0;  // carattere non codificabile
}

int main() {
  string text;  
  cout << "Inserisci una parola: ";
  cin >> text;
  getline(cin, text);
 
for (char c : text) {
    if( c != ' ')
        cout << controlchar(c);
    else
        cout << " ";
  }

for (int i = 0; i < text.length(); i++) {    
   if(text[i] != ' ')
   cout << controlchar(text[i]); 
   else cout << " ";     
}
  cout << endl;

  return 0;
}
 
Caspita pensavo si dovesse mantenere.
Non ho mai usato getline quindi quel cin all'interno della parentesi acquisisce tutte le parole cosa che il cin>>text non fa...
 
getline ha questa firme:

C++:
istream& getline (istream&  is, string& str, char delim);
istream& getline (istream&& is, string& str, char delim);
istream& getline (istream&  is, string& str);
istream& getline (istream&& is, string& str);

il primo parametro è come noti un isstream.
Se guardi la doc per cin, ti dirà:

Object of class istream that represents the standard input stream oriented to narrow characters (of type char). It corresponds to the C stream stdin.

Inoltre sempre su getline:
Get line from stream into string
Extracts characters from is and stores them into str until the delimitation character delim is found (or the newline character, '\n', for (2)).

Qui trovi la doc: https://www.cplusplus.com/reference/string/string/getline/
 
  • Mi piace
Reazioni: MisterMPG
Ultima modifica:
SCusate premettendo che non conosco Java riuscite a creare un codice con Java per questo esercizio e darmi qualche spiegazione?
Grazie a tutti.
 
Stato
Discussione chiusa ad ulteriori risposte.