我有2个函数,其中一个使用Ord()函数加密,另一个用于解密字符串。除扩展的Ascii代码外,它都很好用。
如果我使用字母ê(Ascii代码136),则Ord()函数将返回234,正如我期望的那样,它将返回136。
如果我对加密的字符串进行解密,则得到的结果与原始字符串的结果将有所不同,ê变成j。
有人可以帮忙解决这个问题吗?
procedure TForm1.btnEncryptClick(Sender: TObject);
var
sTempString : string;
iIndex,
i: integer;
begin
sTempString := edtOriginalString.Text ;
for iIndex := 1 to length(sTempString) do
begin
i := ord(sTempString[iIndex]);
i := i shl 1;
sTempString[iIndex] := Char(i);
end;
edtEncryptedString.Text := sTempString;
end;
procedure TForm1.btnDecryptClick(Sender: TObject);
var
sTempString : string;
iIndex,
i : integer;
begin
sTempString := edtEncryptedString.Text ;
for iIndex := 1 to length(sTempString) do
begin
i := ord(sTempString[iIndex]);
i := i shr 1;
sTempString[iIndex] := char(i);
end;
edtDecryptedString.Text := sTempString;
end;
答案 0 :(得分:3)
如果我使用字母ê(Ascii代码136)
不,这实际上是错误的。 ASCII仅包含128个字符(0到127)。
但是,ê是Unicode字符U + 00EA:带圆圈符号的拉丁文小写字母E。
EA(十六进制)的确是234(十进制)。
Delphi字符和字符串在Delphi 2009之前为8位,在Delphi 2009及更高版本中为Unicode。
因此,在您的情况下,Delphi 6是一个8位字符。
因此,您的左移将使您失去最高有效位(MSB),并且您不可能希望将其恢复。
实际上,如果我们考虑ê(234),我们有
1110 1010 (ê)
将位向左移动一步,我们得到
1101 0100
将位向右移动一步,我们得到
0110 1010 (j).
因此,我们丢失了信息。
但是,您的方法将用于ASCII字符(<= 127),因为它们的MSB都为零。 不适用于127以上的任何字符,因为它们都具有一个MSB(因此,即使Ord
确实返回了136,也不会起作用)。>
因此,如果要支持127以上的字符,则需要放弃或重新设计“加密”方法。例如,可以旋转位而不是移动它们。也可以将它们反转(使用not
)。
如果您选择旋转而不是平移,则会得到以下提示:
1110 1010 (ê)
rotate left:
1101 0101
rotate back (right):
1110 1010 (ê)
尽管这与您的实际问题无关,但是您可能仍然想知道为什么Ord
并没有返回您期望的136。
好吧,在Unicode之前(主要是在1990年代和更早的年代),仅存在许多不同的(不兼容)字符编码。通常,一个8位编码/代码页(字符0..255)包含ASCII字符(0..127),然后为其余字符(128..255)做出自己的选择。由于ê不是ASCII字符,这意味着这些“扩展ASCII”代码页中只有一部分可能包含ê,而在包含ê的那些代码页中,实际数字值可能会大不相同。
换句话说,您的消息来源声称ê为136,而您的Delphi程序使用的是不同的8位代码页。
在Unicode的现代世界中,这种问题不再存在。