Search code examples
ccs50caesar-cipher

How to wrap around alphabetically z to a and Z to A after shifting each letter by a number of places?


I am working on a code in which I shift each letter by one place, so (a) becomes (b) and (b) becomes (c) and so on. So far I managed to do that, but I am confronting a problem wrapping around the capital letter (Z) to (A). I can't seem to get the logic how to do that. Any help would be appreciated. Thanks a lot.

#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>

int main(void)
{
    //prompt the user to type in a text.
    string p = get_string("plaintext: ");
    
    //create a variable to refer to the length of the string.
    int n = strlen(p);
    
    
    for (int i = 0; i < n; i++)
    {
        //check if all chars (i) in the string (p) are alphabetical then increment i by 1.
        if (isalpha(p[i]))
        p[i]++;

        {
            //check if i has gone beyond the letter (z) and (Z).
            if ((p[i] > 'z') && (p[i] > 'Z'))
            {
                //if so then subtract 26 letter after z or Z to get back to a or A.
                p[i] = p[i] - 26;
            }

        }
        printf("%c", p[i]);
    }
    printf("\n");
}

Solution

  • an other way closer to the initial program is just to replace

    if ((p[i] > 'z') && (p[i] > 'Z'))
    

    by

    if ((p[i] == 'z'+1) || (p[i] == 'Z'+1))
    

    that avoid to duplicate almost all the code as this is the case in the other answer


    And I think it is more readable to replace

    p[i] = p[i] - 26;
    

    by

    p[i] -= 'z' - 'a' + 1;
    

    The compiler replace 'z' - 'a' + 1 by its value and the expression explain the goal by itself


    And to finish I think it is more clear to do

    if (isalpha(p[i]))
    {
      if ((p[i] == 'z') || (p[i] == 'Z'))
        p[i] -= 'z' - 'a';
      else
        p[i] += 1;
    }
    

    and that remove an increment for nothing

    or to have only one line :

    if (isalpha(p[i]))
      p[i] += ((p[i] == 'z') || (p[i] == 'Z')) ? 'a' - 'z' : 1;
    

    but this is less readable probably


    Out of that

    printf("%c", p[i]);
    

    is expensive and can be replaced by

    putchar(p[i]);