Matt
Matt

Reputation: 87

Caesar cipher in C, upper and lower case

I have to produce Caesar cipher decoder -- for both lower and upper case, but I am not able to think of an easy solution to do this (or at the moment even working one).

At the moment I have this loop to decipher the code by given shift i:

char* s1 = "qrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnop";
int s1s = strlen(s1);
int i = 16;
char tmp[s1s+1];
for (int j = 0; j < s1s; ++j) {
    char tmp_s = (char) ((int) s1[j]-i);
    if(tmp_s<65){
        tmp_s+=58;
    }
    tmp[j]=tmp_s;
}
tmp[s1s]='\0';

Output should be abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ, at the moment it is abcdefghijklmnopqrstuvwxyzABCDEFGHIJQRSTUVWXYZ[\]^_.

I have tried some conditions, but can't really figure out the right one.

Upvotes: 0

Views: 1137

Answers (1)

rocambille
rocambille

Reputation: 15976

Your tests are not complete. Consider the "ASCII space":

\0 ... 'A' ... 'Z' ... 'a' ... 'z' ...

You have here 5 areas:

  1. characters before 'A'.
  2. characters between 'A' and 'Z'.
  3. characters between 'Z' and 'a'.
  4. characters between 'a' and 'z'.
  5. characters after 'z'.

What you need is to handle characters in areas 1 and 3 once shifted (since you're only performing subtractions, area 5 will never be reached).

You should also use characters in your conditions instead of numerical values for readability. Try:

char* s1 = "qrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnop";
int s1s = strlen(s1);
int i = 16;
char tmp[s1s+1];
for (int j = 0; j < s1s; ++j) {
    char tmp_s = (char) ((int) s1[j]-i);
    if(tmp_s < 'A'){ /* "area 1" */
        tmp_s += 'z'-'A' + 1; /* shift between 'a' and 'z' */
    }
    else if(tmp_s < 'a' && s1[j] >= 'a'){ /* "area 3" */
        tmp_s += 'Z'-'a' + 1; /* shift between 'A' and 'Z' */
    }
    tmp[j]=tmp_s;
}
tmp[s1s]='\0';

The code may need further adaptations if you allow i to be high enough to "jump" more than one area.

Upvotes: 1

Related Questions