问题一
我有
var example : array[0..15] of char;
我想将输入值分配给该变量
example := inputbox('Enter Name', 'Name', '');
在高分单元中,我有记录和数组
type
points = record
var
_MemoryName : array[0..15] of char;
_MemoryScore : integer;
end;
var
rank : array[1..3] of points;
var s: string;
a: packed array[0..15] of char;
highscoresdata.position[1]._MemoryName := StrPLCopy(a, s, Length(a)) ;
返回 - > (186):E2010 Incompatible types: 'array[0..15] of Char' and 'PWideChar'
var s: string;
a: packed array[0..15] of char;
s := InputBox('caption', 'Caption', 'Caption');
FillChar(a[0], length(a) * sizeof(char), #0);
Move(s[1], a[0], length(a) * sizeof(char));
scores.rank[1]._MemoryName := <<tried both s and a>> ;
返回(189): E2008 Incompatible types
答案 0 :(得分:5)
问题一
有很多方法。一个是:
procedure TForm1.FormCreate(Sender: TObject);
var
s: string;
a: packed array[0..15] of char;
begin
s := InputBox(Caption, Caption, Caption);
assert(length(s) <= 16);
FillChar(a[0], length(a) * sizeof(char), #0);
Move(s[1], a[0], length(s) * sizeof(char));
end;
但我怀疑,你的原始问题可能会有一个更优雅的解决方案。
问题二
每当您希望函数/过程没有特定参数时,您应该意识到项目的设计可能存在问题。然而,Sender
参数是多余的并不罕见,因为它们几乎无所不在,因为VCL的设计(特别是TNotifyEvent
)。如果您知道接收程序不关心Sender
参数,只需提供任何内容,例如Self
或nil
。
问题三
考虑以下代码:
procedure TForm4.FormCreate(Sender: TObject);
var
a: packed array[0..15] of char;
b: packed array[0..15] of char;
begin
a := b;
end;
这不起作用。你不能像字符串一样对待数组;特别是,你不能像这样分配静态数组(a := b
)。
相反,你必须做一些像......
Move(b[0], a[0], length(a) * sizeof(char));
...或者只是一次循环并复制一个值。但是如果声明一个静态数组类型,上面的简单赋值(a := b
)就可以了:
type
TChrArr = packed array[0..15] of char;
procedure TForm4.FormCreate(Sender: TObject);
var
a: TChrArr;
b: TChrArr;
begin
b := a;
end;
答案 1 :(得分:2)
Andreas为您提供问题1。
问题2
我会安排你的事件处理程序调用另一个方法:
procedure TForm5.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
RespondToEditControlKeyPress;
end;
这样你就可以直接拨打RespondToEditControlKeyPress
。
我猜你想要在没有参数的情况下调用它,因为你希望在修改编辑控件的文本时运行代码。您也许可以使用OnChange
事件。可能OnChange
更合适,因为按键不是将文本导入编辑控件的唯一方法。
顺便说一下,最好在Stack Overflow上一次提出一个问题。
答案 2 :(得分:2)
有关将字符串类型值复制到字符数组类型值的快速方法。我建议这样一个小帮手函数:
procedure StrToCharArray( inputStr:String; var output; maxlen:Integer);
type
ArrayChar = Array[0..1] of Char;
begin
StrLCopy( PChar(@ArrayChar(output)[0]),PChar(inputStr),maxlen);
end;
每次调用它时,传入要复制的最大长度。请记住,如果缓冲区长度为15,则应该传入14作为maxlen,以便为终止 nul 字符留出空间,如果您打算始终终止字符串:
StrToCharArray( UserInputStr, MyRecord.MyField, 14 );
此函数将确保您复制到记录中的数据为空终止,假设这是您想要的。请记住,在固定长度的字符数组中,由您决定规则是什么。 Null终止了吗?用空格或空字符完全填充....字符串和字符数组是如此不同,在两者之间存在多种可能的转换方式。
如果你不打算用nul终止你的字符串,那么你应该使用别人答案中显示的FillChar + Move组合。
答案 3 :(得分:0)
显而易见的答案当然是 不要使用填充的char数组。
请改用字符串。
如果使用ansistring
,则1个字符将始终占用1个字节。
如果您使用shortstring
同上。
Ansistring与Pchar
兼容,packed array of char
是指向function inputbox(a,b,c: ansistring): pchar;
begin
Result:= a+b+c;
end;
var s: ansistring;
begin
s:= inputbox('a','b','c');
end;
的指针。
所以你可以写
packed array of char
一些建议
看起来你正在将代码从c转换为Delphi。
shortstring
与旧(1995)shortstring
完全相同,减去packed array of char
开头的长度字节。
我可以考虑使用ansistring
的唯一原因是当您从磁盘读取数据和从磁盘读取数据时,您有遗留的代码,您不想更改。
我会保留遗留代码以便从磁盘读取和写入,然后将数据传输到ansistring
,然后只使用ansistring
。
这太容易了,德尔福为你做了一切
并且...... stringa:= stringb
速度更快,自动创建和销毁,可以有任意长度(最多2GB),使用更少内存 - 因为相同的字符串只能存储一次(其中表示ansistring
,其中字符串为20个字符,使用ansistrings比char的数组快至少5倍。)
当然最重要的是,unicodestring
无法实现缓冲区溢出错误。
packed array of char
怎么样?
Unicodestring可以使用,但有时在ansistring
和unicodestring之间进行转换时会发生字符转换,因此我建议在此上下文中使用{{1}}。
答案 4 :(得分:0)
你尝试做的事情确实是不可能的:
highscoresdata.position[1]._MemoryName := StrPLCopy(a, s, Length(a));
尝试将一个指针(StrPLCopy的结果,Delphi的最后几个版本中的PWideChar)分配给一个数组,这确实是不可能的。你不能复制那样的数组。我愿意:
StrLCopy(highscoresdata.position[1]._MemoryName, PChar(s),
Length(highscoresdata.position[1]._MemoryName));
这应该有效,IMO是将字符串复制到字符数组的最简单的解决方案。没有必要使用a作为某种中间体,并且使用Move是,IMO,相当低级别因此有点棘手(很容易忘记乘以字符的大小,它是未经检查的,它不是添加#0等,特别是如果您不知道自己到底在做什么。
这个解决方案甚至适用于Delphi 2009之前的Delphi版本,因为它不依赖于角色的大小。
FWIW,我不会使用打包数组。 Packed在当前的Delphi中没有意义,但可能会混淆编译器并使类型不兼容。