C++ Caesar Cipher

profileARapSal
code.docx

// Start with the inclusion of libraries

#include <iostream> //The library of io functions

#include <fstream> //The library of external stream functions

#include <cstdlib> //The library for external errors

#include <string> //The library for string functions

#include <cmath> //The library of C math functions

#include <iomanip> //Allows setting widths, etc. for I/O

#include <stdlib.h>

#include <stdio.h>

#include<vector>

using namespace std;

// Define all of the prototypes for functions used in the program

// Counts the number of unique letters seen

int countunique(int *array, int size);

// Creates the input file and formats it for use by the cipher section.

void createinput(string ifile, string ofile);

// Creates the encoded input file

void createcipher(int key, string ifile, string ofile);

// Finds and counts the number of digrams

int digram(int *pointer, string ifile);

// Counts the letter frequency in the encoded input file

int lettercount(int*, string ifile, string ofile);

// Finds the highest count in the singlton (or any other) array

int singleton(int*, int size);

// Trims an input file to the right size starting at an offset

void trimfile(string ifile, string ofile, int offset, int size);

// Begin the main function for testing

int main(int argc, char* argv[])

{

int count = 0;

int second = 0;

int singlefreq[26];

int *single = singlefreq;

int delta;

int loop; //The loop counter for arguments

int final = 0;

int totalcnt;

int key = -1; //Sets the key value

int len = 0; //The length to investigate for testing

int off; //Holds the offset into the file

double m; //Holds the metric error value

char loopletter;

float percent;

string ifile1 = "";

string ofile1 = "";

string deflt = "c:\\dissertation\\ShiftandSubcipherC++files\\clean.txt";

string ifile2 = "";

string ofile2 = ""; //Holds selected file path names

string cmdarg; //Holds the command line argument

string stop = "l"; //Gives the stop condition, assumes l

string reportfile = "c:\\dissertation\\test\\report.txt";

ofstream outs; //Declare an output stream for reporting

int digramc[676]; //Set up the digram array

int *two = digramc; //Point to the digram array

int dicount = 0; //Holds the count of the number of digrams

int total = 0; //Counts the total number of letters seen for analysis

for (loop = 1; loop<argc; loop++) //Decide if we have arguments or must use defaults

{

if (!argv[1])

{

// cout << "No argument found.\n";

ifile1 = deflt;

}

else

{

cmdarg = argv[loop];

if (cmdarg == "-k")

{

loop++;

key = atoi(argv[loop]);

cout << "key = " << key << endl;

}

if (cmdarg == "-l")

{

loop++;

len = atoi(argv[loop]);

cout << "Run for " << len << " characters.\n";

}

if (cmdarg == "-m")

{

loop++;

m = atof(argv[loop]);

cout << "Run until and error of " << m << "\n";

}

if (cmdarg == "-off")

{

loop++;

off = atoi(argv[loop]);

cout << "Start the analysis " << off << " characters into the file.\n";

}

if (cmdarg == "-stop")

{

loop++;

stop = argv[loop];

cout << "Stop for " << stop << "\n";

}

if (cmdarg == "-i")

{

loop++;

ifile2 = argv[loop];

cout << "Using input file " << ifile2 << "\n";

}

if (cmdarg == "-o")

{

loop++;

ofile2 = argv[loop];

cout << "Using outpuf file " << ofile2 << endl;

}

}

}

for (count = 0; count<26; count++) //Initialize the frequency arrays to no count

{

singlefreq[count] = 0;

}

for (count = 0; count<676; count++) //Initialize the digram array to no count

{

digramc[count] = 0;

}

createinput(ifile2, ofile2);

createcipher(key, ofile2, ofile2);

// cout << ofile2 << endl;

trimfile(ofile2, ofile2, off, len);

totalcnt = lettercount(single, ofile2, ofile2);

cout << "\n\n";

/* for(count=0;count<26;count++)

{

loopletter = 97 + count;

percent = (singlefreq[count]*100/totalcnt);

cout << "For the letter " << loopletter << ", the count = " << setw(10) << setfill('-') << singlefreq[count]

<< " " << setw(4) << percent << "%" << endl;

total = total + singlefreq[count];

}*/

cout << "Total number of letters analyzed " << setw(10) << setfill('-') << total << endl;

delta = singleton(single, 26);

final = delta;

delta = delta + 97;

cout << endl << endl << "The letter E is most likely offset to " << char(delta) << endl;

if (final < 5)

{

final = final + 22;

}

else{

final = final - 4;

}

cout << "This corresponds to a shift of " << final << "\n\n\n";

m = float(abs(final - key)) / float(countunique(single, 26));

// cout << m << "=" << float(abs(final-key)) << "/" << float(countunique(single,26))<< endl;

dicount = digram(two, ofile2);

outs.open(reportfile.c_str(), ios::app); // Open the output stream as a binary input stream

if (outs.fail()) // If the input stream cannot open, report it then close the program

{

cerr << "\n\n ERROR - Cannot open " << reportfile << " for reading.\n";

// return EXIT_FAILURE; //failure return

}

else {

std::cout << "\nOpened the file " << reportfile << ".\n";

}

outs << ifile2 << "," << key << "," << final << "," << len << "," << off << "," << m << endl;

outs.close();

return 0;

}

void createinput(string ifile, string ofile)

{

char ch;

int val = 1;

int count = 0;

// Give the default location of the file containing the data to be read in

string table = "c:\\dissertation\\data.txt"; // Set up a default file for input

string tablein;

string outfile = "c:\\dissertation\\out.txt"; // Set up a default file for output

ifstream ins; // Declare ins an input stream

ofstream outs; // Declare outs and output stream

// cout << "In createinput\n";

if (ifile != "")

{

// cout << "Forming the filename with exenteder\n";

tablein = ifile + ".txt";

// cout << "Creating clean file from " << tablein << endl;

}

else

{

tablein = "i";

}

if (tablein != "i")

{

table = tablein;

}

ins.open(table.c_str(), ios::binary); // Open the input stream as a binary input stream

if (ins.fail()) // If the input stream cannot open, report it then close the program

{

cerr << "\n\n ERROR - Cannot open " << table << " for reading.\n";

// return EXIT_FAILURE; //failure return

}

else {

std::cout << "\nOpened the file " << table << ".\n";

}

// cout << "Have ofile as " << ofile << endl;

if (ofile != "")

{

outfile = ofile + "\\out.txt";

cout << "Creating outfile as " << outfile << endl;

}

outs.open(outfile.c_str(), ios::binary); // Open the output stream as a binary input stream

if (outs.fail()) // If the input stream cannot open, report it then close the program

{

cerr << "\n\n ERROR - Cannot open " << outfile << " for reading.\n";

// return EXIT_FAILURE; //failure return

}

else {

std::cout << "\nOpened the file " << outfile << ".\n";

}

ins >> ch;

// cout << ch; //<< "\n";

while (!ins.eof()){

if (((ch >= 65) && (ch < 91)) || ((ch >= 97) && (ch < 123))) //Check if this is an alpha character

{

if ((ch >= 65) && (ch < 91))

{

ch = ch + 32;

}

// std::cout << ch; // << "\n";

outs << ch;

count++;

}

// std::cout << count << "\n";

ins >> ch;

};

std::cout << "\n\nFinal charater count = " << count << "\n\n\n";

ins.close(); // Close the input stream

// cout << "\nClosed input file " << table << ".\n";

outs.close(); // Close the output file stream

// cout << "\nClosed output file " << outfile << ".\n\n\n";

}

void createcipher(int key, string ifile, string ofile)

{

unsigned char ch;

int offset;

int val = 0;

cout << "Read in a key value of: " << key << endl;

// Give the default location of the file containing the data to be read in

string table = "c:\\dissertation\\out.txt"; // Set up a default file for input

string tablein;

string outfile = "c:\\dissertation\\cipher.txt"; // Set up a default file for output

string keys;

ifstream ins; // Declare ins an input stream

ofstream outs; // Declare outs and output stream

// cout << "In createcipher\n";

if (ifile != "")

{

tablein = ifile + "\\out.txt";

}

else

{

tablein = "i";

}

if (tablein != "i")

{

table = tablein;

}

ins.open(table.c_str(), ios::binary); // Open the input stream as a binary input stream

if (ins.fail()) // If the input stream cannot open, report it then close the program

{

cerr << "\n\n ERROR - Cannot open " << table << " for reading.\n";

// return EXIT_FAILURE; //failure return

}

else {

std::cout << "\nOpened the file " << table << ".\n";

}

if (ofile != "")

{

outfile = ofile + "\\cipher" + ".txt";

}

outs.open(outfile.c_str(), ios::binary); // Open the output stream as binary input stream

if (outs.fail()) // If the input stream cannot open, report it then close the program

{

cerr << "\n\n ERROR - Cannot open " << outfile << " for reading.\n";

// return EXIT_FAILURE; //failure return

}

else {

std::cout << "\nOpened the file " << outfile << ".\n";

}

if (key == -1)

{

while (val == 0)

{

cout << "\n\nPlease input the shift for the cipher (from 1 to 25): ";

cin >> offset;

if ((offset >= 1) && (offset < 26))

{

cout << "\n\nYou have entered an offset of " << offset << ".\n\n\n";

val = 1;

}

else

{

cout << "You have entered an invalid number, you will be prompted again for the right input value.\n";

}

};

}

else

{

offset = key;

}

ins >> ch;

ch = ch + offset;

// cout << ch; //<< "\n";

while (!ins.eof()){

if (ch > 'z') //Check if this is an alpha character

{

ch = ch - 26;

// cout << ch;

}

// std::cout << ch << " " << int(ch) << " " << offset <<" " << ch+offset <<" ;"; // << "\n";

outs << ch;

ins >> ch;

ch = ch + offset;

};

ins.close(); // Close the input stream

// cout << "\n\nClosed input file " << table << ".\n";

outs.close(); // Close the output file stream

// cout << "\nClosed output file " << outfile << ".\n\n\n";

}

int lettercount(int *pointer, string ifile, string ofile)

{

int lettercount = 0;

int offset;

char target;

// Give the default location of the file containing the data to be read in

string table = "c:\\dissertation\\cipher.txt"; // Set up a default file for input

string tablein;

// string outfile = "c:\\dissertation\\cipher.txt"; // Set up a default file for output

ifstream ins; // Declare ins an input stream

// ofstream outs; // Declare outs and output stream

// cout << "In lettercount\n";

if (ifile != "")

{

tablein = ifile + "\\newcipher.txt";

}

else

{

tablein = "i";

}

if (tablein != "i")

{

table = tablein;

}

// cout << "Counting from the file " << table << endl;

ins.open(table.c_str(), ios::binary); // Open the input stream as a binary input stream

if (ins.fail()) // If the input stream cannot open, report it then close the program

{

cerr << "\n\n ERROR - Cannot open " << table << " for reading.\n";

// return EXIT_FAILURE; //failure return

}

else {

std::cout << "\n\nOpened the file " << table << ".\n";

}

ins >> target;

while (!ins.eof())

{

// cout << target << "\n";

lettercount = lettercount + 1;

offset = target - 97;

// cout << offset << endl;

pointer[offset]++;

// cout << pointer[offset] << endl;

ins >> target;

};

cout << "Total " << setw(7) << setfill('-') << lettercount << endl;

ins.close();

// cout << lettercount << endl;

return lettercount;

}

int singleton(int *letter, int size)

{

int loop = 0;

int highest = 0; //Holds the highest letter count to date in the loop

int tempval = 0; //Holds the present value for the letter count

int offset = 0; //Holds the letter offset for the highest value

for (loop = 0; loop<size; loop++)

{

tempval = letter[loop];

if (tempval > highest)

{

highest = tempval;

offset = loop;

}

}

return offset;

}

int digram(int *pointer, string ifile)

{

int lettercount = 0;

int offset1, offset2;

int index;

int let1offset, let2offset;

char target;

char target2;

// Give the default location of the file containing the data to be read in

string table = "c:\\dissertation\\cipher.txt"; // Set up a default file for input

string tablein;

// string outfile = "c:\\dissertation\\cipher.txt"; // Set up a default file for output

ifstream ins; // Declare ins an input stream

// ofstream outs; // Declare outs and output stream

// cout << "In digram\n";

if (ifile != "")

{

tablein = ifile + "\\cipher.txt";

}

else

{

tablein = "i";

}

if (tablein != "i")

{

table = tablein;

}

ins.open(table.c_str(), ios::binary); // Open the input stream as a binary input stream

if (ins.fail()) // If the input stream cannot open, report it then close the program

{

cerr << "\n\n ERROR - Cannot open " << table << " for reading.\n";

// return EXIT_FAILURE; //failure return

}

else {

std::cout << "\n\nOpened the file " << table << ".\n";

}

ins >> target;

ins >> target2;

cout << target << target2;

while (!ins.eof())

{

// cout << target << "\n";

lettercount = lettercount + 1;

// offset = target - 97;

// cout << offset << endl;

// pointer[offset]++;

// cout << pointer[offset] << endl;

target = target2;

ins >> target2;

offset1 = target - 97;

offset2 = target2 - 97;

index = (offset1 * 26) + offset2;

// cout << target << target2 << endl;

// cout << offset1 << " " << offset2 << " " << index << endl;

pointer[index]++;

};

ins.close();

// cout << lettercount << endl;

/* for(offset1=0;offset1<677;offset1++)

{

target2 = (offset1 % 26) + 97;

target = ((offset1 - target2 - 97)/26) + 97;

cout << "Number of " << target << target2 << " = " << pointer[offset1] << endl;

}

*/

cout << "\n\n";

offset2 = singleton(pointer, 676);

cout << offset2 << endl << endl;

let2offset = (offset2 % 26);

let1offset = ((offset2 - let2offset)) / 26;

if (let1offset < 19)

{

let1offset = let1offset + 7;

}

else

{

let1offset = let1offset - 19;

}

if (let2offset < 8)

{

let2offset = let2offset + 19;

}

else

{

let2offset = let2offset - 7;

}

cout << "Calculated the first digram letter offset to be " << let1offset << endl;

cout << "Calculated the second digram letter offset to be " << let2offset << endl << endl;

return lettercount;

}

int countunique(int *array, int size)

{

int cnt = 0; //Number of unique letters seen

int loop; //Loop counter

for (loop = 0; loop<size; loop++)

{

if (array[loop]>0)

{

cnt++;

}

}

return cnt;

}

void trimfile(string ifile, string ofile, int offset, int size)

{

int loop, cnt; //Loop counters

char letter; //Holds the letter from the input file

string cutfile; //The file to cut

string finalfile; //The final cut from the file

ifstream ins; //Declare the input stream

ofstream outs; //Declare an output stream

// cout << "In trimfile\n";

cutfile = ifile + "\\cipher.txt";

finalfile = ofile + "\\newcipher.txt";

// cout << ifile << " " << ofile << endl << endl;

// cout << cutfile << " " << finalfile << endl;

ins.open(cutfile.c_str(), ios::binary); // Open the input stream as a binary input stream

if (ins.fail()) // If the input stream cannot open, report it then close the program

{

cerr << "\n\n ERROR - Cannot open " << cutfile << " for reading.\n";

// return EXIT_FAILURE; //failure return

}

else {

std::cout << "\n\nOpened the file " << cutfile << ".\n";

}

outs.open(finalfile.c_str(), ios::binary); // Open the output stream as a binary input stream

if (outs.fail()) // If the input stream cannot open, report it then close the program

{

cerr << "\n\n ERROR - Cannot open " << finalfile << " for reading.\n";

// return EXIT_FAILURE; //failure return

}

else {

std::cout << "\nOpened the file " << finalfile << ".\n";

}

for (cnt = 0; cnt<offset; cnt++)

{

// cout << cnt << endl;

ins >> letter;

// outs<< letter;

}

for (loop = 0; loop<size; loop++)

{

ins >> letter;

outs << letter;

// cout << cnt << " " << loop << " " << letter << endl;

}

ins.close();

outs.close();

//Close the input and output files

ins.close();

outs.close();

cout << "Closed the files, this program is done.\n";

//return 0;

}

string decryptshift(char letter, int key)

{

int newletter;

string eletter = "";

newletter = int(letter) - key;

if (newletter < 97){

newletter = newletter + 26;

}

if (newletter >= 97 && newletter <= 122){

eletter = char(newletter);

}

return eletter;

}

string decryptfileshift(string& file, int key)

{

int loop;

string dfile;

for (loop = 0; loop < file.length(); loop++){

// cout << file[loop] << endl;

dfile = dfile + decryptshift(file[loop], key);

}

return dfile;

}

char cleancharinfile(char letter)

{

char symbol;

char concat;

symbol = tolower(letter);

if ((int(symbol) >= 97) && (int(symbol) <= 122)){

concat = symbol;

}

else{

concat = char("");

}

return concat;

}

bool is_allowed(string mgram, vector<string>& alloweds)

{

bool success = false;

vector<string>::iterator ptr;

for (ptr = alloweds.begin(); ptr < alloweds.end(); ptr++){

if (*ptr == mgram){

success = true;

break;

}

if (*ptr > mgram){

break;

}

}

return success;

}

int last_key(vector<bool> list)

{

int key = 0;

int i;

for (i = 0; i < (int)list.size(); i++)

{

if (list.at(i) == true)

{

key = i;

}

}

cout << "solution found" << endl;

return key;

}

//return 0;

//The number of wrong words in the input file is subject to the number of non-alphabetics such as numericals and uppercase letters. However, uppercase letters are first converted to lowercase for uniformity.