C中的凯撒密码错误输出

Ceasar cipher in c wrong output

我需要根据基本字符串(即字母表)和整数移动给定字符串的字母。
该函数的目标是保留在基本字符串中。
例子:

string to shift: a b c
key: -6
output: u v w

但我得到的是:

output: [ \ ]

这意味着移位是基于 ascii table 而不是基本字符串完成的。
我很难弄清楚为什么? :(

这是代码

#include <stdio.h>
#include <string.h>

void    cesar(char *str, int shift);

int     main(void)
{
    char    str[1001] = "ikio kyz rg ykiutjk vgmk ja robxk";
    char    temp[1001];

    strcpy(temp, str);

    printf("%s\n", str);
    cesar(temp, -6);
    return (0);
}

void    cesar(char *str, int shift)
{
    char    alphabet[27] = "abcdefghijklmnopqrstuvwxyz";
    char    c;
    int     i;

    i = 0;
    while (str[i] != '[=12=]')
    {
        if (str[i] >= 'a' && str[i] <= 'z')
        {
            c = alphabet[i] + (str[i] - alphabet[i] + shift);
            str[i] = c;
        }
        i++;
    }
    printf("%s\n", str);
}

输出:

ceci est la seconde page d[ li\re

而不是:

ceci est la seconde page du livre

谢谢^^

至少有这些问题:

'a'

形成偏移量

模与余数

%是余数,不是欧氏模。

 // Offset from `a`
 int c = (str[i] - 'a') + shift;

 // modulo
 c %= 26; // c now in range -25 to 25
 // Handle negative values 
 if (c < 26) c += 26;

 // Undo the offset  
 str[i] = c + 'a';

提示:当 shift 接近 INT_MAX.
时,在循环之前执行一次 shift %= 26; 以防止 (str[i] - 'a') + shift 溢出的可能性 再次使用 int c,而不是 char c,以防止溢出。

以下是如何在没有任何错误值的情况下实现转换

    if (str[i] >= 'a' && str[i] <= 'z')
    {
        c = str[i] - 'a'; // 0 <= c < 26
        c += shift;       // any value possible (no limits on `shift`)
        while( c < 0 ) c += 26; // no longer negative
        while( c > 25 ) c -= 26; // no longer 26+
        str[i] = c + 'a';
    }

减去 a 的值将从 ASCII 常量转换为字母索引 (0...25),它可以由密码代码操作。在末尾添加 a 转换回 ASCII。

您的代码所做的是在执行 %26 检查后盲目地向字母添加 shift。这意味着字母表开头之前的字母需要绕过字母表末尾(测试用例中的 'u' 和 'v')未得到更正。