我正在某种编码器/解码器上做代码,现在已经超过2天无法弄清楚奇怪的行为......我希望有人可以理解并向我解释为什么会发生,无论它是什么是...
这是主要代码,它做了事情(我删除了表单的信息,按钮等,只是核心,以避免垃圾)
unit Encoder;
//
interface
//
var
Enc : array [1..71] of Record
Char: Char;
Encr: string;
Enc: array [1..5] of Char;
end;
EncodeBuffer: TStringList;
implementation
{$R *.dfm}
procedure TEncrypter.Encode;
var
s, t, u, h, h2, h3, h4, h5: integer;
begin
s := EncodeBuffer.Count;
h := 0;
h2 := 1;
h3 := 2;
h4 := 3;
h5 := 4;
while h < s do
begin
t := EncodeBuffer.Strings[h].Length;
if t > 0 then
begin
for u := 0 to t-1 do
begin
EncodeBuffer.Strings[h] := EncodeBuffer.Strings[h].Replace(EncodeBuffer.Strings[h].Chars[u], EncodeChar(EncodeBuffer.Strings[h].Chars[u], 1));
end;
end;
h := h + 5;
end;
while h2 < s do
begin
t := EncodeBuffer.Strings[h2].Length;
if t > 0 then
begin
for u := 0 to t-1 do
begin
EncodeBuffer.Strings[h2] := EncodeBuffer.Strings[h2].Replace(EncodeBuffer.Strings[h2].Chars[u], EncodeChar(EncodeBuffer.Strings[h2].Chars[u], 2));
end;
end;
h2 := h2 + 5;
end;
while h3 < s do
begin
t := EncodeBuffer.Strings[h3].Length;
if t > 0 then
begin
for u := 0 to t-1 do
begin
EncodeBuffer.Strings[h3] := EncodeBuffer.Strings[h3].Replace(EncodeBuffer.Strings[h3].Chars[u], EncodeChar(EncodeBuffer.Strings[h3].Chars[u], 3));
end;
end;
h3 := h3 + 5;
end;
while h4 < s do
begin
t := EncodeBuffer.Strings[h4].Length;
if t > 0 then
begin
for u := 0 to t-1 do
begin
EncodeBuffer.Strings[h4] := EncodeBuffer.Strings[h4].Replace(EncodeBuffer.Strings[h4].Chars[u], EncodeChar(EncodeBuffer.Strings[h4].Chars[u], 4));
end;
end;
h4 := h4 + 5;
end;
while h5 < s do
begin
t := EncodeBuffer.Strings[h5].Length;
if t > 0 then
begin
for u := 0 to t-1 do
begin
EncodeBuffer.Strings[h5] := EncodeBuffer.Strings[h5].Replace(EncodeBuffer.Strings[h5].Chars[u], EncodeChar(EncodeBuffer.Strings[h5].Chars[u], 5));
end;
end;
h5 := h5 + 5;
end;
end;
procedure TEncrypter.Decode;
var
s, t, u, h, h2, h3, h4, h5: integer;
begin
s := EncodeBuffer.Count;
h := 0;
h2 := 1;
h3 := 2;
h4 := 3;
h5 := 4;
while h < s do
begin
t := EncodeBuffer.Strings[h].Length;
if t > 0 then
begin
for u := 0 to t-1 do
begin
EncodeBuffer.Strings[h] := EncodeBuffer.Strings[h].Replace(EncodeBuffer.Strings[h].Chars[u], DecodeChar(EncodeBuffer.Strings[h].Chars[u], 1));
end;
end;
h := h + 5;
end;
while h2 < s do
begin
t := EncodeBuffer.Strings[h2].Length;
if t > 0 then
begin
for u := 0 to t-1 do
begin
EncodeBuffer.Strings[h2] := EncodeBuffer.Strings[h2].Replace(EncodeBuffer.Strings[h2].Chars[u], DecodeChar(EncodeBuffer.Strings[h2].Chars[u], 2));
end;
end;
h2 := h2 + 5;
end;
while h3 < s do
begin
t := EncodeBuffer.Strings[h3].Length;
if t > 0 then
begin
for u := 0 to t-1 do
begin
EncodeBuffer.Strings[h3] := EncodeBuffer.Strings[h3].Replace(EncodeBuffer.Strings[h3].Chars[u], DecodeChar(EncodeBuffer.Strings[h3].Chars[u], 3));
end;
end;
h3 := h3 + 5;
end;
while h4 < s do
begin
t := EncodeBuffer.Strings[h4].Length;
if t > 0 then
begin
for u := 0 to t-1 do
begin
EncodeBuffer.Strings[h4] := EncodeBuffer.Strings[h4].Replace(EncodeBuffer.Strings[h4].Chars[u], DecodeChar(EncodeBuffer.Strings[h4].Chars[u], 4));
end;
end;
h4 := h4 + 5;
end;
while h5 < s do
begin
t := EncodeBuffer.Strings[h5].Length;
if t > 0 then
begin
for u := 0 to t-1 do
begin
EncodeBuffer.Strings[h5] := EncodeBuffer.Strings[h5].Replace(EncodeBuffer.Strings[h5].Chars[u], DecodeChar(EncodeBuffer.Strings[h5].Chars[u], 5));
end;
end;
h5 := h5 + 5;
end;
end;
function TEncrypter.EncodeChar(Sign: Char; Encoder: integer) : Char;
var
t: integer;
begin
for t := 1 to 71 do
begin
if Sign = enc[t].Char then
begin
Result := enc[t].Enc[Encoder];
Break;
end
else
Result := Sign;
end;
end;
function TEncrypter.DecodeChar(Sign: Char; Encoder: integer) : Char;
var
t: integer;
begin
for t := 1 to 71 do
begin
if Sign = enc[t].Enc[Encoder] then
begin
Result := enc[t].Char;
Break;
end
else
Result := Sign;
end;
end;
我在FormCreate
事件上创建了一个Enc数组,它使用随机字符顺序填充Enc[1 to 71].Char
和Enc[1 to 71].Enc[1 to 5]
;
代码是(或者至少应该是),以便它为每个第5行使用不同的编码列表(第1行enc[x].enc[1]
,第2行enc[x].enc[2]
,然后第5行{{ 1}},第6行返回enc[x].enc[5]
,依此类推......)
如果我从Memo1编码5行,那么:
enc[x].enc[1]
我得到一些随机单词,每个单词有5个字符,但是当解码它时,我会被返回
Memo1
Memo2
Memo3
Memo4
Memo5
(注意第3行中较低的m字母);
如果我再对此进行编码,我会得到与第一种情况完全相同的编码字符串列表,只有在这里,第3行的第3个字符! (wtf?)改变与第一个相同。
所以,对于Memo3,我得到Memo1
Memo2
memo3
Memo4
Memo5
,而对于memo3,我得到q7M0e
,这对我来说没有意义,因为char的位置应该是相同的,就我所知的代码而言。
这里有什么我想念的,在上面的代码中是明显的吗?
评论是否需要我粘贴完整表格(单位)的代码和exe示例,我会在网上给它并链接到...
编辑:
这是我正在编码/解码的“密钥”:http://txt.do/128b
答案 0 :(得分:7)
您的方法存在一些问题。
一个问题是您使用String.Replace()
,它将一个Char
的所有次出现替换为另一个Char
。替换给定的Char
后,您可能会在循环中使用不同的值替换相同的索引,从而在循环时丢弃数据。
另一个问题是你的解码逻辑。您允许使用5种不同的Char
之一对每个未编码的Char
进行编码。如果Char
数组中Enc[1..71].Enc
值的编码Encoder
值与Enc[1..71].Char
的相同值重复,则您将无法知道哪个Encoder
用于解码。您的数组仅仅是随机数是不够的,但它们对于function TEncrypter.EncodeChar(Sign: Char; Encoder: integer) : Char;
var
t: integer;
begin
for t := 1 to 71 do
begin
if Sign = Enc[t].Char then
begin
Result := Enc[t].Enc[Encoder];
Exit;
end;
end;
Result := Sign;
end;
function TEncrypter.DecodeChar(Sign: Char; Encoder: integer) : Char;
var
t: integer;
begin
for t := 1 to 71 do
begin
if Sign = Enc[t].Enc[Encoder] then
begin
Result := Enc[t].Char;
Exit;
end;
end;
Result := Sign;
end;
procedure TEncrypter.Encode;
var
t, u, h: integer;
s: String;
begin
for h := 0 to EncodeBuffer.Count-1 do
begin
s := EncodeBuffer.Strings[h];
t := Length(s);
if t > 0 then
begin
for u := 0 to t-1 do
begin
s[u+1] := EncodeChar(s[u+1], (h mod 5) + 1);
end;
EncodeBuffer.Strings[h] := s;
end;
end;
end;
procedure TEncrypter.Decode;
var
t, u, h: integer;
s: String;
begin
for h := 0 to EncodeBuffer.Count-1 do
begin
s := EncodeBuffer.Strings[h];
t := Length(s);
if t > 0 then
begin
for u := 0 to t-1 do
begin
s[u+1] := DecodeChar(s[u+1], (h mod 5) + 1);
end;
EncodeBuffer.Strings[h] := s;
end;
end;
end;
的相同值也必须是唯一的。
此外,您的循环是多余的,过于复杂。它们可以大大简化。
尝试更像这样的东西:
// FormCreate
var
I, J, K, L: Integer;
Temp: Array[1..71] of Char;
NumInTemp: Integer;
begin
...
// initialize Enc[].Char as needed...
for I := 1 to 71 do
begin
Enc[I].Char := ...;
end;
// uniquely initialize each Enc[].Enc array for one value of Encoder...
for I := 1 to 5 do
begin
for J := 1 to 71 do
Temp[J] := ...; // must be unique for this iteration of I...
NumInTemp := 71;
// randomly assign Temp array to Enc[I].Enc array
for J := 1 to 71 do
begin
K := 1 + Random(NumInTemp);
Enc[J].Enc[I] := Temp[K];
for L := K+1 to NumInTemp do
Temp[L-1] := Temp[L];
Dec(NumInTemp);
end;
end;
...
end;
var
Enc : array [32..126] of Record
Char: Char;
Encr: string;
Enc: array [1..5] of Char;
end;
EncodeBuffer: TStringList;
function TEncrypter.EncodeChar(Sign: Char; Encoder: integer) : Char;
var
t: integer;
begin
if (Sign >= #32) and (Sign <= #126) then
Result := Enc[Ord(Sign)].Enc[Encoder]
else
Result := Sign;
end;
function TEncrypter.DecodeChar(Sign: Char; Encoder: integer) : Char;
var
t: integer;
begin
for t := Low(Enc) to High(Enc) do
begin
if Sign = Enc[t].Enc[Encoder] then
begin
Result := Enc[t].Char;
Exit;
end;
end;
Result := Sign;
end;
procedure TEncrypter.Encode;
var
u, h: integer;
s: String;
begin
for h := 0 to EncodeBuffer.Count-1 do
begin
s := EncodeBuffer.Strings[h];
for u := Low(s) to High(s) do
s[u] := EncodeChar(s[u], (h mod 5) + 1);
EncodeBuffer.Strings[h] := s;
end;
end;
procedure TEncrypter.Decode;
var
u, h: integer;
s: String;
begin
for h := 0 to EncodeBuffer.Count-1 do
begin
s := EncodeBuffer.Strings[h];
for u := Low(s) to High(s) do
s[u] := DecodeChar(s[u], (h mod 5) + 1);
EncodeBuffer.Strings[h] := s;
end;
end;
如果然后扩展阵列以允许所有可打印的ASCII字符,而不仅仅是其中的71个字符,那么代码会变得更简单:
// FormCreate
var
I, J, K, L: Integer;
Temp: Array[32..126] of Char;
NumInTemp: Integer;
begin
...
for I := Low(Enc) to High(Enc) do
Enc[I].Char := Char(I);
for I := 1 to 5 do
begin
for J := Low(Temp) to High(Temp) do
Temp[J] := Char(J);
NumInTemp := Length(Temp);
for J := Low(Enc) to High(Enc) do
begin
K := Low(Temp) + Random(NumInTemp);
Enc[J].Enc[I] := Temp[K];
for L := K+1 to (Low(Temp)+NumInTemp) do
Temp[L-1] := Temp[L];
Dec(NumInTemp);
end;
end;
end;
Enc[].Enc
如果您设置单独的解码器表而不是使用TEncrypter.DecodeChar()
,则可以将TEncrypter.EncodeChar()
简化为{{1}}使用的类似查找,而无需使用循环。我将把它作为练习留给你。
答案 1 :(得分:3)
假设我以字符串“abc”开头。
我想用“c”替换所有“a”,用“Q”替换所有“b”,并用“7”替换所有“c”。 也许我会写:
S := 'abc';
S := S . Replace ( 'a', 'c' );
S := S . Replace ( 'b', 'Q' );
S := S . Replace ( 'c', '7' );
结果是'7Q7'。哎呀!为什么不用“c”代替“a”? 嗯,确实如此。 在第一次调用Replace之后,S是'cbc'。 第二次通话后,S是'cQc'。 最后一次通话将'c'替换为'7'。
我想你在这里也做同样的事情。 除非我们看到你如何填充Enc结构,否则我无法给你角色代码字符的具体结果。