Ok, let's try this again, step by step.
Any caesar cypher performs a transformation
Code:
cryptchar = (plainchar + shift) % alphabet_size
the inverse of this transformation is
Code:
plainchar = (cryptchar - shift) % alphabet_size
since the we are working with ASCII encoded characters we need to shift the origin from 0 to a before the transformation and back to 0 afterwards
Code:
plainchar = plainchar1 - 'a' // shift origin to a
cryptchar = (plainchar + shift) % alphabet_size
cryptchar1 = cryptchar + 'a' // shift origin back to 0
So far it's all really simple. The tricky bit is due to c++ implementation of the % operator. Usually modulus operations have range [0, n-1]. The c++ % operator has range [0, n-1] for positive input (the a in a % b) and [-n+1, 0] for negative input.
This is not an issue in the encryption since plainchar + shift is always positive (if the shift is positive, I'll show later that restricting the shift to the range [0, alphabet_size-1] still gives all possible shifts).
On the other hand on the decryption step there might be problems. If shift > cryptchar1 then cryptchar - shift will be a negative number which will give you a final result that is out of the intended range.
To solve this problem you need to ensure that cryptchar1 - shift is never negative.
One solution is to repeatedly add alphabet_size to the result untile the result is positive (since you are working in modulus arithmetic adding an integer multiple of alphabet_size doesn't change the final result).
The other soultion is to recognize the fact that (a - b) % c = (a + c - b) % c (remember adding any integer multiple of c doesn't change the result)
Thus the decryption routine can be written as
Code:
plainchar = (cryptchar + alphabet_size - shift) % alphabet_size
alphabet_size - shift is never negative as long as shift < alphabet_size
Why do you only need shifts in the range [0, alphabet_size - 1]?
Assume we have a bad_shift that is outside that range. We can break down bad shift into
Code:
bad_shift = a * alphabet_size + shift
where a is an arbitrary integer and 0 <= shift < alphabet_size.
Since we are working in modulus arithmetic the a * alphabet_size component has no effect to the final reusult and we can safely ignore it.
Hope this helps
PS
Originally Posted by
L_U_K_E
Code:
ciphertext += ( ( (a[i] - 'a') + (offset - offset2) / (offset3 * offset) - offset2) %26) + 'a';
I hope you realise that all those calculations with the 3 offsets could be done once and stored in a single variable