5

我正在加密如下,但不知道如何防止大写字母超出范围时进入其他符号,同样小写字母超出小写字母的范围。我怎样才能让它们转一圈并停止溢出?谢谢

    int size = strlen(plain_text);
int arrayelement = 0;
for(arrayelement = 0; arrayelement < size; arrayelement++)
{
    if (islower(plain_text[arrayelement]))
    {
        ciphered_text[arrayelement] = (int)(plain_text[arrayelement] + shiftkey);
    }
    else if (isupper(plain_text[arrayelement]))
    {
        ciphered_text[arrayelement] = (int)(plain_text[arrayelement] + shiftkey);
    }
}

ciphered_text[size] = '\0';
printf("%s", ciphered_text);
4

4 回答 4

1

我猜你使用像 char 这样的类型,所以一个不溢出的简单解决方案是

int tmp_ciphered = (my_char + shift) % 0xff;
char ciphered = (char)(tmp_ciphered);

然后你转身不要溢出,这是一个戒指

于 2012-11-15T23:20:03.970 回答
1

这复制了(几乎完全一样)c++ simple Caesar cipher algorithm

请注意,我不同意该帖子中接受的答案。基本上,您必须使用 ((c-'a'+shift) % 26) + 'a' 之类的东西将字符映射回范围。然而,假设你的角色在'a'..'z'中。使用 c >= 'a' && c <= 'z' 而不是 islower 可能更安全,因为我不确定语言环境将如何在非英语系统上发挥作用。isupper 和其他范围类似。最后,当 char 不在任一范围内时,您需要一个 else 子句来处理。

于 2012-11-15T23:20:29.120 回答
1

唯一真正可移植的方法是为输入域构建一个查找表,并基于非线性假设手动构建字符。

即使对于 的受限域['a'..'z','A'..'Z'],假设 'A'..'Z' 是连续的,语言标准也没有定义,并且可证明并非总是如此。对于任何持不同看法的反对者,我会在此链接中引导您查看图表中字符的序数位置,并密切注意假设序列中间的死区。如果您认为“没有人再使用 EBCDIC”,让我向您保证 AS/400 和 OS/390 都还不错(并且可能现在正在处理您的美国税收,因为 IRS 是 IBM 最大的客户之一)。

事实上,C 标准对此非常明确:

C99-5.2.1.3在源和执行基本字符集中,上述十进制数字列表中 0 之后的每个字符的值都应比前一个字符的值大一。

甚至在字符集的任何其他部分都没有提到定义的顺序甚至隐含的顺序。事实上,'0'..'9'它还有一个独特的属性:它们是唯一保证不受语言环境更改影响的字符。

因此,与其假设字符存在线性延续,同时对标准的可疑沉默嗤之以鼻,让我们定义我们自己的地图。我不会像往常一样在这里内联代码;如果你仍然和我在一起,你真的有兴趣了解并且可能会阅读和批评下面的代码。但我将总结一下它是如何工作的:

  1. 静态声明两个字母,长度加倍 (A..ZA..Z,a..za..z)。
  2. 声明两个足够大的数组(加密和解密)以容纳(1<<CHAR_BIT)条目。
  3. 使用与其索引对应的值完全初始化两个数组。例如:a[0]=0, a[1]=1,...
  4. 用与移位宽度 Ex 对应的适当值填充加密数组中的每个位置,这些位置是我们从 (1) 开始的字母表的一部分。a['a'] = 'g'对于ROT5。
  5. 通过从字母表的尾部向后应用相反的移位方向来镜像 (4)。例如:`a['g'] = 'a';

您现在可以使用加密数组作为一个简单的表来将输入文本转换为密文:

enc-char = encrypt[ dec-char ];
dec-char = decrypt[ enc-char ];

如果您认为仅仅为了获得源级平台独立性似乎需要大量工作,那么您是完全正确的。但是你会惊讶于人们试图冒充“多平台”的#ifdef #endif地狱。平台无关代码的核心目标不仅是定义公共源代码,还要定义行为。不管是什么平台,上面的概念都会起作用。(而不是看到#ifdef)。

感谢您花时间阅读这个惨败。这么看似简单的问题……


示例 main.cpp

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

// global tables for encoding. must call init_tables() before using
static char xlat_enc[1 << CHAR_BIT];
static char xlat_dec[1 << CHAR_BIT];

void init_tables(unsigned shift)
{
    // our rotation alphabets
    static char ucase[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ";
    static char lcase[] = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
    int i=0;

    // ensure shift is below our maximum shift
    shift %= 26;

    // prime our table
    for (;i<(1 << CHAR_BIT);i++)
        xlat_enc[i] = xlat_dec[i] = i;

    // apply shift to our xlat tables, both enc and dec.
    for (i=0;i<(sizeof(ucase)+1)/2;i++)
    {
        xlat_enc[ lcase[i] ] = lcase[i+shift];
        xlat_enc[ ucase[i] ] = ucase[i+shift];
        xlat_dec[ lcase[sizeof(lcase) - i - 1] ] = lcase[sizeof(lcase) - i - 1 - shift];
        xlat_dec[ ucase[sizeof(ucase) - i - 1] ] = ucase[sizeof(ucase) - i - 1 - shift];
    }
}


// main entrypoint
int main(int argc, char *argv[])
{
    // using a shift of 13 for our sample
    const int shift = 13;

    // initialize the tables
    init_tables(shift);

    // now  drop the messsage to the console
    char plain[] = "The quick brown fox jumps over the lazy dog.";
    char *p = plain;
    for (;*p; fputc(xlat_enc[*p++], stdout));
    fputc('\n', stdout);

    char cipher[] = "Gur dhvpx oebja sbk whzcf bire gur ynml qbt.";
    p = cipher;
    for (;*p; fputc(xlat_dec[*p++], stdout));
    fputc('\n', stdout);

    return EXIT_SUCCESS;
}

输出

Gur dhvpx oebja sbk whzcf bire gur ynml qbt.
The quick brown fox jumps over the lazy dog.
于 2012-11-16T07:44:25.063 回答
0

您可以从字面上实现它:

“如果它们超出范围”:

if (ciphered_text[arrayelement] > 'z')

“让他们转一圈,停止溢出”:

ciphered_text[arrayelement] -= 26;

在您的上下文中:

if (plain_text[arrayelement] >= 'a' && plain_text[arrayelement] <= 'z')
{
    ciphered_text[arrayelement] = (int)(plain_text[arrayelement] + shiftkey);
    if (ciphered_text[arrayelement] > 'z')
        ciphered_text[arrayelement] -= 26;
}

(假设您使用 ACSII 编码的英文文本,并且shiftkey在 1...25 范围内,就像它应该的那样)

于 2012-11-18T13:48:19.010 回答