-6

I have an assignment using a version of Ceasar cipher but it shifts characters in a file based on user input. For instance, if the user enters the shift value as 1, it would change 'a' to 'b'. I've tried typing to the out file and adding the shift value to the characters but it doesnt output anything to the out1 file and I can't figure out the right way to type this so the code does what I want it to do. Any info would help, here's my code:

#include <iostream>
#include <iomanip>
#include <fstream>
#include <cctype>
using namespace std;

double Percent(double&, double&);
int main()
{
    //Declare user variables
    int shift;
    char ifilename[25], ofilename[25], ch;
    ifstream in1;
    ofstream out1;
    double other = 0, letter, nums = 0;

    //Attach files
    do {
        in1.clear(); //clear status flags

    //Prompt user to enter name of input file and amount of shift
    cout << "Please enter the name of the input file." << endl;
    cout << "Filename: ";
    cin >> ifilename;

    //Open file name
    in1.open(ifilename);

    //Error message if no file
    if (!in1)
        cout << "That is not a valid file. Try again\n";
}

while (!in1);

do {
    out1.clear(); //clear status flags

    cout << "Please enter the name of the output file." << endl;
    cout << "Filename: ";
    cin >> ofilename;

    out1.open(ofilename);

    //Error message if no file
    if (!out1)
        cout << "That is not a valid file. Try again\n";
}
while (!out1);


//prompt user to enter shift
cout << "Please intput the shift amount: ";
cin >> shift;
cout << "Processing complete" << endl;


double count = 0;
int sum = 0, i = 0;

    while (!in1.eof())   // while not end of input file
    {
        in1.get(ch);       // read a character from input file using get()
        out1 << ch;        //print to output
        count++;           //count how many characters

        i = ch;
        if (i > 47 && i < 58) //count number of numbers
            nums++;
        else if ((i > 31 && i < 48) || (i > 57 && i < 65) || (i > 90 && i < 97) || (i > 122 && i < 127))
            other++; // count number of other characters
        else if ((i > 64 && i < 91) || (i > 96 && i < 123))
            letter++; // count number of letters

        // type to output file and shift characters
        out1 << ch + shift;
    }

//Tell user file input is complete and is now printing statistics
cout << "\nShifted input file Complete. Now printing statistics " << endl;

//Show statistics for file
cout << "\nStatistics for file: " << ifilename << endl;
cout << "------------------------------------------------";


//Show characters in file and stats before shift
cout << "\n\nTotal # of characters in file: " << count << endl;
cout << "Statistics before shift: " << endl;


cout << "\n\nCategory" << setw(30) << "How many in file" << setw(20) << "% of file" << endl;
cout << "----------------------------------------------------------------" << endl;
cout << "Letters" << setw(25) << letter << setw(20) << setprecision(4) << letter / count * 100 << " %" << endl;
cout << "Digits" << setw(26) << nums << setw(20) << setprecision(4) << nums / count * 100  << " %" << endl;
cout << "Other" << setw(27) << other << setw(20) << setprecision(4) << other / count * 100  << " %" << endl;

//Show user stats after shift
cout << "\nStatistics after shift: " << endl;


cout << "\n\nCategory" << setw(30) << "How many in file" << setw(20) << "% of file" << endl;
cout << "----------------------------------------------------------------" << endl;
cout << "Letters" << setw(25) << letter << setw(20) << setprecision(4) << Percent(letter, count)  << " %" << endl;
cout << "Digits" << setw(26) << sum << setw(20) << setprecision(4) << nums / count * 100  << " %" << endl;
cout << "Other" << setw(27) << nums << setw(20) << setprecision(4) << other / count * 100  << " %" << endl;



//Close files
out1.close();
in1.close();
return 0;
}

double Percent(double&, double&)
{
    double sum, letter, count;
    sum = letter / count * 100;
    return sum;
}
  • 1
    "Caesar" is the correct spelling. – Jon Kalb Mar 18 '18 at 23:17
  • 2
    Always try to develop new functionality *in isolation* as much as possible, and get it working perfectly before trying to integrate it with other code. In this case, try writing code that reads one file and writes another, with hard-coded file names, no user interaction and no cipher. – Beta Mar 18 '18 at 23:19
  • 1
    And when you used your debugger to step through your program, one line at a time, and observe its behavior as it runs, including the values of all variables, what observations did you make? There are multiple bugs in the shown code. `while (!in1.eof())` -- [that's always a bug](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong). `out1 << ch + shift;`. The result of an addition is an `int` value. This will write an int value to `out1`, and not a single character. There are probably more bugs, these are just the most apparent ones. – Sam Varshavchik Mar 18 '18 at 23:20
  • @SamVarshavchik How do I shift it to a different ASCII value then if I dont use the variable shift? The shift is based on user input so it isnt a predefined number that I already know – Holly Thorsted Mar 18 '18 at 23:33
  • @HollyThorsted `double count = 0;` -- Why is `count` a `double`? Why isn't it an `int`? Also, use `isalpha()`, `isdigit()`, etc. to determine if a character is an alphabetic character or a digit. The system knows what is a character or digit -- that isn't your job to assume. Also, do not use magic numbers such as 57, 123, etc. – PaulMcKenzie Mar 18 '18 at 23:35
  • It doesn't matter whether it's predetermined, or not. The result of adding an integer value to a `char` is always an `int`. That's how C++ works. Doesn't matter if what you're adding is another variable, or a constant. You must force the result of an addition to a `char`, explicitly. Open your C++ book to the chapter that explains how to use casts, and you should find more information there. – Sam Varshavchik Mar 18 '18 at 23:48
  • You also need to account for character shifts wrapping around. If you shift 'z' by 1, it should be 'a'. But if you don't account for that, you're going to get something weird. – BessieTheCookie Mar 19 '18 at 01:36
  • Please use character literals instead of their decimal ASCII values, e.g `'A'` instead of 48. – Thomas Matthews Mar 19 '18 at 02:12

1 Answers1

1

A simple implementation of the Caesar Cipher is to use a string of valid characters and the remainder operator, %.

char Encrypt_Via_Caesar_Cipher(char letter, unsigned int shift)
{
  static const std::string vocabulary = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  const std::string::size_type position = vocabulary.find(letter);
  char c = letter;
  if (position != std::string::npos)
  {
     const std::string::size_type length = vocabulary.length();
     c = vocabulary[(position + shift) % length];
  }
  return c;
}
Thomas Matthews
  • 52,985
  • 12
  • 85
  • 144