异常 EInvalidPointer 因为在数组中使用 Unicode 字符
Exception EInvalidPointer because using Unicode chars in array
我正在尝试通过在 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
异常消失但它不支持 Unicode
所以我认为这与 Arrays
或 Unicode
有关
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') = 0
、ord('B') - ord('A') = 1
等。
这两个字符数组对我来说似乎毫无意义。您也可以直接索引到字符串中。我会通过删除这两个数组来重写代码。
我想我也会避免使用连接来填充字符串。因为您提前知道它的长度,所以在一开始就分配它。直接分配给每个索引元素。
不知道你为什么认为TStringList
不支持Unicode。确实如此。
您显示的代码可以大大简化:
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;
我正在尝试通过在 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
异常消失但它不支持 Unicode
所以我认为这与 Arrays
或 Unicode
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') = 0
、ord('B') - ord('A') = 1
等。
这两个字符数组对我来说似乎毫无意义。您也可以直接索引到字符串中。我会通过删除这两个数组来重写代码。
我想我也会避免使用连接来填充字符串。因为您提前知道它的长度,所以在一开始就分配它。直接分配给每个索引元素。
不知道你为什么认为TStringList
不支持Unicode。确实如此。
您显示的代码可以大大简化:
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;