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')未得到更正。
我需要根据基本字符串(即字母表)和整数移动给定字符串的字母。
该函数的目标是保留在基本字符串中。
例子:
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')未得到更正。