001: #include <iostream>
002: #include <fstream>
003: #include <string>
004: #include <sstream>
006: using namespace std;
007: 
008: /**
009:    Prints usage instructions.
010:    @param program_name the name of this program
011: */
012: void usage(string program_name)
013: {  cout << "Usage: " << program_name
015: << " [-d] [-kn] infile outfile\n"; 016: exit(1); 017: } 019: /** 020: Prints file opening error message 021: @param filename the name of the file that could not be opened 022: */ 023: void open_file_error(string filename) 024: { cout << "Error opening file " << filename << "\n"; 026: exit(1); 027: } 029: /** 030: Computes correct remainder for negative dividend. 031: @param a an integer 032: @param n an integer > 0 033: @return the mathematically correct remainder r such that 034: a - r is divisible by n and 0 <= r and r < n 035: */ 036: int remainder(int a, int n) 037: { if (a >= 0) return a % n; 040: else return n - 1 - (-a - 1) % n; 042: } 044: /** 045: Encrypts a character using the Caesar cipher. 046: @param ch the character to encrypt 047: @param k the encryption key 048: @return the encrypted character 049: */ 050: char encrypt(char ch, int k) 051: { const int NLETTER = 'Z' - 'A' + 1; 053: if ('A' <= ch && ch <= 'Z') 054: return static_cast<char>('A' + remainder(ch - 'A' + k, NLETTER)); 056: if ('a' <= ch && ch <= 'z') 057: return static_cast<char>('a' + remainder(ch - 'a' + k, NLETTER)); 059: return ch; 060: } 062: /** 063: Encrypts a stream using the Caesar cipher. 064: @param in the stream to read from 065: @param out the stream to write to 066: @param k the encryption key 067: */ 068: void encrypt_file(istream& in, ostream& out, int k) 069: { char ch; 071: while (in.get(ch)) out.put(encrypt(ch, k)); 073: } 075: /** 076: Converts a string to an integer, e.g. "3" -> 3. 077: @param s a string representing an integer 078: @return the equivalent integer 079: */
080: int string_to_int(string s) 081: { istringstream instr(s); 083: int n; 084: instr >> n; 085: return n; 086: } 087: 088: int main(int argc, char* argv[]) 089: { bool decrypt = false; 091: int key = 3; 092: int nfile = 0; /* the number of files specified */ 093: ifstream infile; 094: ofstream outfile; 095: 096: if (argc < 3 or argc > 5) usage(string(argv[0])); 097: 098: int i; 099: for (i = 1; i < argc; i++) 100: { string arg = string(argv[i]); 101: if (arg.length() >= 2 and arg[0] == '-') 102: /* it is a command line option */ 103: { char option = arg[1]; 105: if (option == 'd') decrypt = true; 107: else if (option == 'k') 108: key = string_to_int(arg.substr(2, arg.length() - 2)); 109: } 110: else 111: { nfile++; 113: if (nfile == 1) 114: { infile.open(arg.c_str()); 116: if (infile.fail()) open_file_error(arg); 117: } 118: else if (nfile == 2) 119: { outfile.open(arg.c_str()); 121: if (outfile.fail()) open_file_error(arg); 122: } 123: } 124: } 125: 126: if(nfile != 2) usage(string(argv[0])); 127: 128: if (decrypt) key = -key; 129: 130: encrypt_file(infile, outfile, key); 131: infile.close(); 132: outfile.close(); 133: return 0; 134: }