Trouble understanding a shift calculation

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • heiro1
    New Member
    • Jan 2013
    • 29

    Trouble understanding a shift calculation

    Hey all!

    I was going over this code to read a file on my desktop that decrypts a cesar cipher code and I am stuck trying to figure out how the shift is calculated in this program.

    From what I can tell, Max e's is the shifted letter with the highest frequency. Since e's are the most common letter in English, the program is trying to set the highest frequency char in the cipher, to an 'e' in English. Which is good, as far as it goes, but there are many phrases where e's are NOT the most frequent letter, and then it will fall on it's face.

    So, how can I tell the program to guess at the most frequent cipher letter to be an e in plain text BUT in case it isn't, then proceed to try an e shifted to the second most frequent letter in the text, and so on, until I find it?

    A friend helped with that part but has poor English so it is difficult for him to explain it to me. Can someone please elaborate? Assistance is greatly appreciated! Let me know what you think:

    Code:
    #include <iostream>
    #include <string>
    #include <cctype> // isalpha, islower, isupper, functions
    #include <fstream>
    using namespace std;
    
    string caesarShift(string text, int shift);
    int main()
    {
        int maxEs = 0;       // # of e's in maxString
        int currentEs = 0;    // # of e'sin currentString
        string maxString;       // decrypted caesar shift with most e's
        string currentString;    //decrypted caesar shift
        
        string cipher;       // Stores cipher text
        char ch;    // Stores currentcharacter for reading
        ifstream fin("/Users/jasonrodriguez/Desktop/encrypted.txt");   //opens "encrypted.txt" file
        while( fin.get(ch) )    // readseach char into the cipher till EOF
        {
            cipher += ch;
        }
        fin.close();    // be safe andclose file
        
        for(int i=0; i < 26; i++)
        {
            currentEs =0;    // Reset counter
            currentString =caesarShift(cipher, i);    // get shifted text
            for(unsigned int x=0; x <currentString.size(); x++) // check each character of stringarray
            {
                if(currentString[x] == 'e' || currentString[x] == 'E') // check fore's
                {
                    currentEs++;    // increment Ecounter
                }
            }
            if(currentEs > maxEs) //if currentEs is greater than maxEs, replace max with current
            {
                maxEs =currentEs;
                maxString= currentString;
            }
        }
        cout << maxString << endl;
        return 0;
    }
    
    /**
     string caesarShift(string text, int shift)
     Decrypts Caesar Shift using text and shift
     */
    string caesarShift(string text, int shift)
    {
        shift = shift % 26;    // Morethan 26 is redundant and unneeded
        char ch = 0; // holds current character
        char chs = 0;    // holds shiftedcharacter
        for(unsigned int i=0; i < text.size();i++)
        {
            ch = text[i];
            if( isalpha(ch) )
            {
                chs = ch -shift; // reverse shifting
                if( (islower(ch) && chs < 'a' )  // If is lowercase andshifted value is lower than 'a'
                   ||
                   ( isupper(ch) && chs < 'A' ) ) // Ifis uppercase and shifted value is lower than 'A'
                {
                    chs += 26;    // Add 26(number ofletters) to get back to the correct place in alphabet
                }
                text[i] =chs;    // Set character to shifted character
            }
        }
        return text;
    }
    Last edited by heiro1; Mar 12 '13, 10:39 PM. Reason: Being more concise
  • heiro1
    New Member
    • Jan 2013
    • 29

    #2
    I think if I shift a character by a shift amount the character may or may not be out of bounds:

    'a' + 3 is 'd' ok,

    'x' + 3 is '{' not ok.

    So if the character is over 'z' take away 26, if under 'a' add 26. can be a usable function.

    However, can someone please explain to me how the shift is calculated in the program and is applied it to the file? It has me totally stumped :(

    Comment

    • heiro1
      New Member
      • Jan 2013
      • 29

      #3
      I can't connect how "shift" is implemented in this particular program.

      This is a start:

      I need to map the letters 'A' through 'Z' (assuming only uppercase letters) to the integers 0 through 25.

      n = c - 'A';

      Now I perform the shift with modulus arithmetic:

      n = (n + shift) % 26;

      Finally map back to a letter:

      p = n + 'A';

      but can anyone help connect the dots to how shift is used in this program? M friend added it in all confusing to me.

      Comment

      • donbock
        Recognized Expert Top Contributor
        • Mar 2008
        • 2427

        #4
        This program assumes that the character codes for the lowercase letters (a-z) is contiguous; it assumes the same for the uppercase letters (A-Z). The C Standard permits compiler implementations to use character encodings that violate this assumption. The assumption holds for ASCII encoding, but fails for EBCDIC. Furthermore, it is hard-coded for a 26-letter alphabet.

        Input to the caesarShift function is a plaintext message; output is an equivalent encrypted message.
        • Line 57 indicates that only alphabetic characters are encrypted.
        • Line 59 replaces each alphabetic character with the one three positions to its left (Z becomes W, Y becomes V, etc). This replacement preserves case (uppercase letters remain uppercase; same for lowercase letters).
        • Lines 60-65 handle the wraparound cases. Assuming ASCII encoding, the character code for 'A' is 65. Subtracting 3 yields 62 which is less than 'A', so we add 26, which yields 88, which is the code for 'X'.

        Comment

        Working...