/**************************************************************************** ** COPYRIGHT (C): 1996 Cay S. Horstmann. All Rights Reserved. ** PROJECT: Computing Concepts with C++ ** FILE: caesar.cpp ** NOTE TO STUDENTS: This file has been edited to be compatible with older ** compilers. If your compiler fully supports the ANSI/ISO C++ ** standard, remove the line #include "ccc_ansi.cpp". You can also remove ** the lines #ifndef CCC_ANSI_H and #endif ****************************************************************************/ #include "ccc_ansi.cpp" #ifndef CCC_ANSI_H #include #include #include #include using namespace std; #endif void usage(string program_name) /* PURPOSE: Prints usage instructions RECEIVES: program_name - the name of this program */ { cout << "Usage: " << program_name << " [-d] [-kn] infile outfile\n"; exit(1); } void open_file_error(string filename) /* PURPOSE: Prints file opening error message RECEIVES: filename - the name of the file that could not be opened */ { cout << "Error opening file " << filename << "\n"; exit(1); } int remainder(int a, int n) /* PURPOSE: Compute correct remainder for negative dividend RECEIVES: a - an integer n - an integer > 0 RETURNS: the mathematically correct remainder r such that a - r is divisible by n and 0 <= r and r < n */ { if (a >= 0) return a % n; else return n - 1 - (-a - 1) % n; } char encrypt(char ch, int k) /* PURPOSE: Encrypt a character using the Caesar cipher RECEIVES: ch - the character to encrypt k - the encryption key RETURNS: the encrypted character */ { const int NLETTER = 26; if ('A' <= ch && ch <= 'Z') return static_cast('A' + remainder(ch - 'A' + k, NLETTER)); if ('a' <= ch && ch <= 'z') return static_cast('a' + remainder(ch - 'a' + k, NLETTER)); return ch; } void encrypt_file(ifstream& in, ofstream& out, int k) /* PURPOSE: Encrypt a file using the Caesar cipher RECEIVES: in - the file to read from out- the file to write to k - the encryption key */ { char ch; while (in.get(ch)) out.put(encrypt(ch, k)); } int string_to_int(string s) /* PURPOSE: Convert a string to an integer, e.g. "3" -> 3 RECEIVES: s - a string representing an integer RETURNS: the equivalent integer */ { istringstream instr(s); int n; instr >> n; return n; } int main(int argc, char* argv[]) { bool decrypt = false; int key = 3; int nfile = 0; /* the number of files specified */ ifstream infile; ofstream outfile; if (argc < 3 or argc > 5) usage(string(argv[0])); int i; for (i = 1; i < argc; i++) { string arg = string(argv[i]); if (arg.length() >= 2 and arg[0] == '-') /* it is a command line option */ { char option = arg[1]; if (option == 'd') decrypt = true; else if (option == 'k') key = string_to_int(arg.substr(2, arg.length() - 2)); } else { nfile++; if (nfile == 1) { infile.open(arg.c_str()); if (infile.fail()) open_file_error(arg); } else if (nfile == 2) { outfile.open(arg.c_str()); if (outfile.fail()) open_file_error(arg); } } } if(nfile != 2) usage(string(argv[0])); if (decrypt) key = -key; encrypt_file(infile, outfile, key); infile.close(); outfile.close(); return 0; }