Delphi在字符串中改变Chars - 误解了行为 - XE3

Tha*_*arc -3 delphi

我在某种编码器/解码器上做代码,现在已经超过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;
Run Code Online (Sandbox Code Playgroud)

我对创建的Enc阵列FormCreate事件,填充Enc[1 to 71].CharEnc[1 to 71].Enc[1 to 5]用随机字符顺序;

代码是(或至少应该是),以便它为每个第5行使用不同的编码列表(第1 enc[x].enc[1]行,第2行enc[x].enc[2],然后第5行enc[x].enc[5],第6行返回enc[x].enc[1]等等......)

如果我从Memo1编码5行,它们是:

Memo1
Memo2
Memo3
Memo4
Memo5
Run Code Online (Sandbox Code Playgroud)

我得到一些随机的单词,每个单词有5个字符,但是当解码它时,我得到了回复

Memo1
Memo2
memo3
Memo4
Memo5 
Run Code Online (Sandbox Code Playgroud)

(注意第3行中较低的m字母);

如果我再对此进行编码,我得到与第一种情况完全相同的编码字符串列表,只有在这里,第3行的第3个字符!(wtf?)改变与第一个相同.所以,对于Memo3我得到了q7M0e,对于memo3我得到了q7q0e,这对我来说没有意义,因为char的位置应该是相同的,据我所知的代码.

这里有什么我想念的,在上面的代码中是明显的吗?

评论是否需要我粘贴完整表格(单位)的代码和exe示例,我会在网上给它并链接到那个...

编辑:

这是我正在编码/解码的"密钥":http://txt.do/128b

Rem*_*eau 7

您的方法存在一些问题.

一个问题是你的使用String.Replace(),它取代了一个与另一个的所有出现.替换给定的后,您可以在循环中使用不同的值替换相同的索引,从而在循环时丢弃数据.CharCharChar

另一个问题是你的解码逻辑.您允许每个未编码的Char编码为5个不同的Chars中的一个.如果这些编码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;
Run Code Online (Sandbox Code Playgroud)

// 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;
Run Code Online (Sandbox Code Playgroud)

如果然后扩展阵列以允许所有可打印的ASCII字符,而不仅仅是其中的71个字符,那么代码会变得更简单:

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;
Run Code Online (Sandbox Code Playgroud)

// 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;
Run Code Online (Sandbox Code Playgroud)

如果您设置一个单独的解码器表而不是使用Enc[].Enc,您可以简化TEncrypter.DecodeChar()为使用的类似查找TEncrypter.EncodeChar(),而不必使用任何循环.我会把它作为锻炼给你.