异常EInvalidPointer因为在数组中使用Unicode字符

时间:2015-10-07 23:08:35

标签: arrays delphi unicode delphi-xe

我正在尝试使用Delphi XE8中的Unicode字符来更改字符样式, 一切顺利,除非我得到密切的申请 这里的错误Exception EInvalidpointer代码

procedure ChangeStyle(OriginalText, DecoratedText: TsMemo; DecoList: TsListBox);
var
  StyleChars, TempText: string;
  Len, I: Integer;
  TextArray, StyleArray: array of UnicodeString;
begin
  // Put Style chars in array
  StyleChars := DecoList.Items.Strings[DecoList.ItemIndex];
  SetLength(StyleArray, 23);
  for I := 1 to 23 do
    StyleArray[I] := Copy(StyleChars, I, 1);

  // Put originl text in array
  Len := OriginalText.GetTextLen;
  SetLength(TextArray, Len +1);
  for I := 1 to Len do
    TextArray[I] := Copy(OriginalText.Text, I, 1);

  // Set style to chars

  for I := 1 to Len do
  begin
    if (TextArray[I] = 'A') or (TextArray[I] = 'a') then
      TempText := TempText + StyleArray[1]
    else if (TextArray[I] = 'B') or (TextArray[I] = 'b') then
      TempText := TempText + StyleArray[2]
    else if (TextArray[I] = 'C') or (TextArray[I] = 'c') then
      TempText := TempText + StyleArray[3]
    else if (TextArray[I] = 'D') or (TextArray[I] = 'd') then
      TempText := TempText + StyleArray[4]
    else if (TextArray[I] = 'E') or (TextArray[I] = 'e') then
      TempText := TempText + StyleArray[5]
    else if (TextArray[I] = 'F') or (TextArray[I] = 'f') then
      TempText := TempText + StyleArray[6]
    else if (TextArray[I] = 'G') or (TextArray[I] = 'g') then
      TempText := TempText + StyleArray[7]
    else if (TextArray[I] = 'H') or (TextArray[I] = 'h') then
      TempText := TempText + StyleArray[8]
    else if (TextArray[I] = 'I') or (TextArray[I] = 'i') then
      TempText := TempText + StyleArray[9]
    else if (TextArray[I] = 'J') or (TextArray[I] = 'j') then
      TempText := TempText + StyleArray[10]
    else if (TextArray[I] = 'K') or (TextArray[I] = 'k') then
      TempText := TempText + StyleArray[11]
    else if (TextArray[I] = 'L') or (TextArray[I] = 'l') then
      TempText := TempText + StyleArray[12]
    else if (TextArray[I] = 'M') or (TextArray[I] = 'm') then
      TempText := TempText + StyleArray[13]
    else if (TextArray[I] = 'N') or (TextArray[I] = 'n') then
      TempText := TempText + StyleArray[14]
    else if (TextArray[I] = 'O') or (TextArray[I] = 'o') then
      TempText := TempText + StyleArray[15]
    else if (TextArray[I] = 'P') or (TextArray[I] = 'p') then
      TempText := TempText + StyleArray[16]
    else if (TextArray[I] = 'Q') or (TextArray[I] = 'q') then
      TempText := TempText + StyleArray[17]
    else if (TextArray[I] = 'R') or (TextArray[I] = 'r') then
       TempText := TempText + StyleArray[18]
    else if (TextArray[I] = 'S') or (TextArray[I] = 's') then
      TempText := TempText + StyleArray[19]
    else if (TextArray[I] = 'W') or (TextArray[I] = 'w') then
      TempText := TempText + StyleArray[20]
    else if (TextArray[I] = 'X') or (TextArray[I] = 'x') then
      TempText := TempText + StyleArray[21]
    else if (TextArray[I] = 'Y') or (TextArray[I] = 'y') then
      TempText := TempText + StyleArray[22]
    else if (TextArray[I] = 'Z') or (TextArray[I] = 'z') then
      TempText := TempText + StyleArray[23]
    else
      TempText := TempText + TextArray[I];

  end;
  DecoratedText.Text := TempText;
end;

我尝试了TextArray := nil;StyleArray := nil,但没有解决它;
还试过TextArray, StyleArray: array of String;
当我使用TStringList时,Exception消失但它不支持Unicode 所以我认为这是关于ArraysUnicode

的问题

2 个答案:

答案 0 :(得分:2)

SetLength(StyleArray, 23);
for I := 1 to 23 do
  StyleArray[I] := Copy(StyleChars, I, 1);

你在这里写出超出数组末尾的内容。动态数组使用从零开始的索引。因此,有效索引为0到22(含)。这解释了您遇到的运行时异常。

鉴于其他地方的基于单一的索引,您可能想要分配一个额外的元素:

SetLength(StyleArray, 24);

并简单地忽略索引为0的第一个元素。

但是,我怀疑大部分代码都可以删除,正如我在下面解释的那样。

巨大的if语句可以用一些算术代替。请注意ord('A') - ord('A') = 0ord('B') - ord('A') = 1等。

两个角色阵列对我来说似乎毫无意义。您也可以直接索引到字符串中。我通过删除这两个数组重新编写代码。

我想我也会避免使用连接来填充字符串。因为你事先知道它的长度,所以在开始时分配它。直接分配给每个索引元素。

我不知道为什么你认为TStringList不支持Unicode。确实如此。

答案 1 :(得分:1)

您展示的代码可以大大简化:

procedure ChangeStyle(OriginalText, DecoratedText: TsMemo; DecoList: TsListBox);
var
  StyleChars, TempText: string;
  Len, I, Idx: Integer;
  Ch: Char;
begin
  // Put Style chars in array
  StyleChars := DecoList.Items.Strings[DecoList.ItemIndex];

  // make sure the array is big enough
  Assert(Length(StyleChars) >= 23, 'StyleChars must be at least 23 characters');

  // Get original text
  TempText := OriginalText.Text;
  Len := Length(TempText);

  // Set style to chars    
  for I := 1 to Len do
  begin
    Ch := TempText[I];
    case Ch of
      'A'..'S', 'W'..'Z': begin
        // convert uppercase letters A..Z into indexes 0..25
        Idx := Ord(Ch) - Ord('A');
        // no styles for letters T..V, so decrement the indexes for W..Z
        if Idx >= 22 then Dec(Idx, 3);
        // Now replace the character
        TempText[I] := StyleChars[Idx+1];
      end:
      'a'..'s', 'w'..'z': begin
        // convert lowercase letters a..z into indexes 0..25
        Idx := Ord(Ch) - Ord('a');
        // no styles for letters t..v, so decrement the indexes for w..z
        if Idx >= 22 then Dec(Idx, 3);
        // Now replace the character
        TempText[I] := StyleChars[Idx+1];
      end;
    end;
  end;

  DecoratedText.Text := TempText;
end;