我需要根据一个基本字符串(即字母表)和一个整数来移动给定字符串的字母。
函数的目标是保持在基字符串内
示例:
string to shift: a b c
key: -6
output: u v w
但是我得到:
output: [ ]
这意味着移位是基于ascii表而不是基本字符串完成的。
我想不通为什么?(
下面是代码
#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("%sn", 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] != ' ')
{
if (str[i] >= 'a' && str[i] <= 'z')
{
c = alphabet[i] + (str[i] - alphabet[i] + shift);
str[i] = c;
}
i++;
}
printf("%sn", str);
}
输出:
ceci est la seconde page d[ lire
代替:
ceci est la seconde page du livre
谢谢^ ^
如何实现移位而不产生任何不正确的值
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检查后盲目地向字母添加移位。这意味着在字母表开始之前的字母,需要包裹在字母表末尾的字母(在你的测试用例中是'u'和'v')不会被纠正。
至少这些问题:
与'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
,以防止溢出。