唯一真正可移植的方法是为输入域构建一个查找表,并基于非线性假设手动构建字符。
即使对于 的受限域['a'..'z','A'..'Z']
,假设 'A'..'Z' 是连续的,语言标准也没有定义,并且可证明并非总是如此。对于任何持不同看法的反对者,我会在此链接中引导您查看图表中字符的序数位置,并密切注意假设序列中间的死区。如果您认为“没有人再使用 EBCDIC”,让我向您保证 AS/400 和 OS/390 都还不错(并且可能现在正在处理您的美国税收,因为 IRS 是 IBM 最大的客户之一)。
事实上,C 标准对此非常明确:
C99-5.2.1.3在源和执行基本字符集中,上述十进制数字列表中 0 之后的每个字符的值都应比前一个字符的值大一。
甚至在字符集的任何其他部分都没有提到定义的顺序甚至隐含的顺序。事实上,'0'..'9'
它还有一个独特的属性:它们是唯一保证不受语言环境更改影响的字符。
因此,与其假设字符存在线性延续,同时对标准的可疑沉默嗤之以鼻,让我们定义我们自己的硬地图。我不会像往常一样在这里内联代码;如果你仍然和我在一起,你真的有兴趣了解并且可能会阅读和批评下面的代码。但我将总结一下它是如何工作的:
- 静态声明两个字母,长度加倍 (A..ZA..Z,a..za..z)。
- 声明两个足够大的数组(加密和解密)以容纳
(1<<CHAR_BIT)
条目。
- 使用与其索引对应的值完全初始化两个数组。例如:
a[0]=0
, a[1]=1
,...
- 用与移位宽度 Ex 对应的适当值填充加密数组中的每个位置,这些位置是我们从 (1) 开始的字母表的一部分。
a['a'] = 'g'
对于ROT5。
- 通过从字母表的尾部向后应用相反的移位方向来镜像 (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.