将每个字母移动多个位置后,如何按字母顺序环绕 z 到 a 和 Z 到 A?

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

我正在编写一个代码,其中我将每个字母移动一个位置,因此 (a) 变为 (b),(b) 变为 (c),依此类推。到目前为止,我设法做到了这一点,但我遇到了将大写字母 (Z) 环绕到 (A) 的问题。我似乎无法理解如何做到这一点。 任何帮助,将不胜感激。 非常感谢。

#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");
}

您需要将 increments/checks 分成大写和小写块,因为尽管字符 a ... zA ... Z 最有可能按顺序排列,它们将是不同个序列。

循环中的这些内容:

    for (int i = 0; i < n; i++) {
        //check if all chars (i) in the string (p) are alphabetical then increment i by 1.
        if (islower(p[i])) { // Lowercase letter check ...
            p[i]++;
            //check if i has gone beyond the letter (z).
            if (p[i] > 'z') {
                //if so then subtract 26 letter after z to get back to a.
                p[i] = p[i] - 26;
            }

        }
        else if (isupper(p[i])) { // Uppercase letter check ...
            p[i]++;
            //check if i has gone beyond the letter (Z).
            if (p[i] > 'Z') {
                //if so then subtract 26 letter after Z to get back to A.
                p[i] = p[i] - 26;
            }

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

(此外,我假设在您的代码中,{ after p[i]++; 是错字 - 否则,您检查每个字符,即使它不是字母。你的缩进表明这不是你想要的。)

另一种更接近初始程序的方法就是替换

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

来自

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

避免重复几乎所有代码,因为在另一个答案中就是这种情况


而且我认为替换

更具可读性
p[i] = p[i] - 26;

来自

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

编译器用它的值替换 'z' - 'a' + 1,表达式自己解释目标


最后,我认为这样做更清楚

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

并且白白删除一个增量

或者只有一行:

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

但这可能不太可读


其中

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

价格昂贵,可以用

代替
putchar(p[i]);