Friday 14 September 2018

Caesar cipher - a simple program

I did some previous articles on cipers, the first one being simple subsitution ciphers. There, I talked about the Caesar cipher, where a simple shift is used for encoding. The code given below is for a simple program for the purpose.

The code is in c++. First, the program reads the input file (input.txt), code it, and output the coded version to output1.txt. Then, it reads the output1.txt file, decodes it, and outputs the result to output2.txt. Decoding is done by using -1*original shift as the shift.
The explanation follows the code.


/* 
 * File:   main.cpp
 * Author: 88415XC
 *
 * Created on September 14, 2018, 3:52 PM
 */

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <cstring>

using namespace std;

char line[250]={'\0'};                  //For input data
char line_c[250]={'\0'};                //For coded/decoded data
//array storing all simple and capital letters. this program is not case sensitive.
char code[2][26]={{'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'},
{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}};
//the 'value' assigned to the corresponding character in the code array.
int vals[26]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25};

/*
 * get the value corresponding to the char input
 */
int get_val(char character){
    int val = -1;
    for (int i=0; i<26;i++){
        if ((character==code[0][i])||(character==code[1][i])){
            val = vals[i];
            break;
        }
    }
    return val;
}

/*
 * gets the character corresponding to the char input
 */
char get_char(int val){
    char char_1 = '\0';
    for (int i=0; i<26;i++){
        if (val==vals[i]){
            char_1 = code[0][i];
            break;
        }
    }
    return char_1;
}

/*
 * Encodes/decodes the input data. 
 * All non-letter characters are ignored. All letters are shifted by the 
 * specified shift.
 */
void encode_caesar(int shift){
    int temp=0;
    char temp_1 = '\0';
    for (int i = 0; i<250; i++){
        if (line[i]=='\0') break;
        temp=get_val(line[i]);
        if (temp!=-1){
            temp = (temp+shift)%26;
            if (temp<0) temp=temp+26;
            temp_1=get_char(temp);
            line_c[i]=temp_1;
        }
        else{
            line_c[i]=line[i];
        }
    }
}

/*
 * 
 */
int main(int argc, char** argv) {
    ifstream input1;
    fstream output1;
    ofstream output2;
    
    input1.open("input1.txt",ios::in);
    output1.open("output1.txt",ios::out);
    
    //code input1 and put to output 1
    while(!(input1.eof())){
        memset(line,'\0',250);
        memset(line_c,'\0',250);
        input1>>line;
        encode_caesar(8);
        output1<<line_c<<endl;;
    }
    input1.close();
    output1.close();
    
    output1.open("output1.txt",ios::in);
    output2.open("output2.txt",ios::out);
    
    //decode output1 and put to output 2
    while(!(output1.eof())){
        memset(line,'\0',250);
        memset(line_c,'\0',250);
        output1>>line;
        encode_caesar(-8);
        output2<<line_c<<endl;
    }
    output1.close();
    output2.close();
    

    return 0;
}

First, the includes:
iostream: mainly for debugging.
fstream: for reading and writing to files.
cstring: because memset doesn't work without it (explanation will follow later.

Global variables: I hope the comments explain things sufficiently. The reason for using a 'val' array instead of using the array index of code is to allow more flexibility (as in, you could technically mix up the order as long as it's from 0-25 and make it a little more difficult to decode than the standard Caesar cipher)

get_val and get_char: These two functions are used to look up the values necessary in the arrays. Get_val looks up the number corresponding to the character it has to look up, and get_char does the opposite. Note that the program is not case sensitive, so get_char will return an upper case letter every time. In case of an error, get val returns -1, get char returns the null character (\0).

encode_caesar: This function handles one line at a time. It goes through the line one character at a time. Each character is converted to the corresponding value. If the value is -1, the same character is written to the coded string (line_c). If not, the shift (positive or negative) is added, and the modulus is taken. Here, you have to add the divisor (25) if the value is negative because '%' operator is actually the remainder from division. The resulting value is then converted back to a character and written to the coded string. As you probably noticed, numbers, punctuation marks, etc are not changed and written back as it is.

Moving on to the main program, it's basic functionality is as described in the introduction. Going step by step, first, the file handles are defined. I really need only 2 here, but I used three for the three files I was using. ifstream is for input, fstream is for both input and output, and ofstream is for output.
Then input.txt and output1.txt are opened, the former in input mode and the latter in output mode. The following while loop reads input.txt line by line until the end of the file. I should probably mention that c++ considers a space the end of the line, and the next word is considered another line. memset is used to clear line and line_c before reading the input to clear any of the previous line left in them. Once the line is read, encode_caesar is called with the required shift (8 in this case, but you can, technically, use any value you like). Then the coded line is written to output.txt.
The next part functions almost identically, with output1.txt as the input and output2.txt as the output. The only difference is, as this decodes the text, the previous shift multiplied by -1 is used with encode_caesar (-8 in this case).

I hope this is helpful. Until next time!



No comments:

Post a Comment

How to write a character who is smarter than you

We all have that one character (or few) who is significantly smarter than the writer. So, as a writer, how do you write such a character con...