Search code examples
c++asciicaesar-cipher

Absolute value not getting added correctly in ascii


I have written a small program for Ceasar cipher in C++. I think I am doing good with the logic. However, the ASCII addition is going wrong for some odd reason which I am unable to understand. Here is my code: Something is wrong at this line: "s[i] = (abs(s[i])) + k;"

I am giving input as follows:

2

xy

87

Output Should be: gh

I am getting the output as: ed.

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

int main(){
    int n;
    cin >> n;
    string s;
    cin >> s;
    int k;
    cin >> k;
    k = k % 26;
    for(int i = 0; i<s.size(); i++){
        if((abs(s[i]) >=65 && abs(s[i]) <=90) || (abs(s[i]) >= 97 && abs(s[i]) <= 122)){
            cout << "k is: "<<k << endl; //k should be 9
            //for x abs(s[i]) should be 120
            cout << "Absolute value is: "<<abs(s[i]) <<endl;

            s[i] = (abs(s[i])) + k; // thish is not 129.. i am getting 127
            cout << "After adding K: "<<abs(s[i]) << endl; 
            if((abs(s[i]) > 90) && (abs(s[i]) < 97))
                s[i] = abs(s[i]) - 26;
            if(abs(s[i]) > 122){
                s[i] = abs(s[i]) - 26;
            }                            
        }
    }
    for(int i =0 ; i< s.size(); i++)
        cout<<s[i];
    return 0;
}

Any help will be appreciated. Thanks.


Solution

  • this line:

    s[i] = (abs(s[i])) + k;
    

    computes a value higher than 127. Strings use char types internally, so you're putting a value out of range in s[i]: implementation defined: modulo, truncature...

    Substracting 26 afterwards doesn't help: the data is already destroyed.

    Fix: work with an integer all the way, and assign back to s[i] in the end:

    for(int i = 0; i<s.size(); i++){
        int v = s[i];
        if((abs(v) >=65 && abs(v) <=90) || (abs(v) >= 97 && abs(v) <= 122)){
            cout << "k is: "<<k << endl; //k should be 9
            //for x abs(v) should be 120
            cout << "Absolute value is: "<<abs(v) <<endl;
    
            v = (abs(v)) + k; // integer won't overflow
            cout << "After adding K: "<<abs(v) << endl; 
            if((abs(v) > 90) && (abs(v) < 97))
                s[i] = abs(v) - 26;
            if(abs(v) > 122){
                s[i] = abs(v) - 26;
            }                            
        }
    }
    

    I've tested that and I get gh all right (and it's faster because there's less array access to s[i])