Samstag, 26. März 2011

Caesar Cypher in C++

Habe mal wieder etwas herumgespielt und diesmal eine neue Klasse für die Caesar Cypher in C++ verfasst, diesmal orientiere ich mich an dem Verfahren, wie ich es in Kryptografie gelernt habe. Damit aber es etwas einfacher ist habe ich extra eine abstrakte Basisklasse erstellt:


class Cypher
{
protected:
///////////////Konstanten/////////////////////////

//Abstand zwischen Klein- und Großbuchstaben
static int const SPACE = 32;

///////////////Attribute///////////////////////////

//der Text, der Codiert oder Decodiert werden soll
string message;




///////////////Methoden/////////////////////////////

//ersetzt alle Großbuchstaben im Text durch Kleinbuchstaben
void toLowerCaseString()
{
    for(int i = 0; i < message.length(); i++)

    { 
      if((int)message[i] < 97) 
         message[i] += SPACE; 
    }   
}
public: 
/////////////////Konstruktor/////////////////////////// 
Cypher(string _message) 

   message = _message; 
   toLowerCaseString(); 

/////////////////Virtuelle Methoden///////////////////// 

//Methode zum Codieren von Nachrichten, muss individuell implementiert werden 
virtual string encode() = 0; 

//Methode zum Decodieren von Nachrichten, muss individuell implementiert werden 
virtual string decode() = 0; 

//Methode zum Einlesen eines Strings mit Leerzeichen (Empfohlen zum 
//Verarbeiten von Strings mit Leerzeichen) 
static void getInput(string &str) 

    char c; 
    cin.get(c); 
    while((int)c != 10)
    { 
        str += c; 
        cin.get(c); 
    } 

}; 



Nachdem die nun steht heist es ganz einfach ableiten und die virtuellen Methoden implementieren. Desweiteren brauchen wir nur noch ein weiteres Attribut für den Buchstaben, der als Key arbeitet und eine Methode zum umwandeln des Keys in einen Kleinbuchstaben.


class CaesarCypher: protected Cypher
{
protected:
////////////////////Attribute///////////////////////////////

//der Buchstabe, der zur Codierung/Decodierung (muss der Gleichebuchstabe sein) 

//verwendet werden soll
char key;

////////////////////Methoden/////////////////////////////////

//ersetzt den key durch den Kleinbuchstaben
void toLowerCaseChar()
{
    if((int)key < 97) 

      key += SPACE; 
}
public: 
//////////////////////Konstruktor///////////////////////////// 
CaesarCypher(string _message, char _key):Cypher(_message) 

   key = _key; toLowerCaseChar(); 


///////////////////////Methoden/////////////////////////////// 
string encode() 

   string cypher = ""; 
   int k = (int)key - 97; 
   int c; 

   for(int i = 0; i < message.length(); i++) 
   { 
      while(message[i] == 64 && i < message.length()) 
         i++; 
      c = (int)message[i] - 97; 
      c = c + k;
      c = c % 26; 
      c += 97; 
      cypher += (char)c; 
   } return cypher; 


string decode() 

   int k = (int)key - 97; 
   int m; 
   string decypher = ""; 

   for(int i = 0; i < message.length(); i++)
   { 
      while(message[i] == 64 && i < message.length()) 
         i++;
      m = (int)message[i] - 97; 
      m = m - k; 
      
      if(m < 0)
         m = 26 + m;

      m = m % 26; 
      m += 97; 
      decypher += (char)m; 
   } 
   return decypher; 

};

Vielleicht noch mal kurz den Gedanken hinter der Codierung erklären: Die Idee ist ganz simpel, ich nehme einen Buchstaben aus dem String, speicher seinen ASCII, der nun der eines Kleinbuchstaben entspricht, und bringe seinen Wert auf eine Zahl zwischen 0 und 25. Diese Zahl Addiere ich jetzt mit dem ASCII des Keys, der auf die gleiche Art umgewandelt wurde, und Teile die Summe durch 26 (weil 26 Buchstaben) und nehme den Rest als neuen Buchstaben. Den Rest, den ich also erhalte Addiere ich wieder mit 97 um den richtigen ASCII Wert zu erhalten. Das ganze hänge ich an einen neuen String ran um sicher zu gehen, dass die Original Nachricht erstmal nicht verändert wird und somit Fehlerquellen Minimiere. Beim Decodieren erfolgt das gleiche bloß halt mit Subtraktion in einem Ring anstelle einer Addition.

Keine Kommentare:

Kommentar veröffentlichen