将字符串分配给字符数组
问题一
我
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 不兼容类型:'array[0..15] of Char' 和 '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 不兼容类型
Question One
I have
var example : array[0..15] of char;
I want to assign the value from an input to that variable
example := inputbox('Enter Name', 'Name', '');
In the highscores unit I have record and array
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)) ;
returns -> (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>> ;
returns (189): E2008 Incompatible types
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
问题一
方法有很多。一是:
但我怀疑,对于你原来的问题可能有一个更优雅的解决方案。
问题二
每当您希望函数/过程没有特定参数时,您应该意识到项目的设计可能存在问题。然而,
Sender
参数是多余的并不罕见,因为由于 VCL 的设计(特别是TNotifyEvent
),它们几乎无处不在。如果您知道接收过程不关心Sender
参数,只需给它任何东西,例如Self
或nil
。问题三
考虑这段代码:
这不起作用。你不能像对待字符串一样对待数组;特别是,您不能像这样分配静态数组 (
a := b
)。相反,您必须执行类似...
...或者只是循环并一次复制一个值。但是,如果您声明静态数组类型,则上述简单赋值 (
a := b
) 确实有效:Question One
There are many ways. One is:
But there might be a more elegant solution to your original problem, I suspect.
Question Two
Every time you wish a function/procedure didn't have a particular argument, you should realize that there might be a problem with the design of the project. Nevertheless, it isn't uncommon that
Sender
parameters are superfluous, because they are almost omnipresent because of the design of the VCL (in particular, theTNotifyEvent
). If you know that the receiving procedure doesn't care about theSender
parameter, simply give it anything, likeSelf
ornil
.Question Three
Consider this code:
This doesn't work. You cannot treat arrays like strings; in particular, you cannot assign static arrays like this (
a := b
).Instead, you have to do something like...
...or simply loop and copy one value at a time. But the above simple assignment (
a := b
) does work if you declare a static array type:Andreas 已为您解答了问题 1。
问题 2
我会安排您的事件处理程序调用另一个方法:
这样您就可以直接调用
RespondToEditControlKeyPress
。我猜您想在不带参数的情况下调用它,因为您希望在修改编辑控件的文本时运行代码。您也许可以使用
OnChange
事件来代替。OnChange
可能更合适,因为按键并不是将文本输入编辑控件的唯一方法。顺便说一句,最好在 Stack Overflow 上一次问一个问题。
Andreas has you covered for question 1.
Question 2
I would arrange that your event handler called another method:
That way you can just call
RespondToEditControlKeyPress
directly.I'd guess that you want to call it with no parameters because you want code to run when the edit control's text is modified. You could perhaps use the
OnChange
event instead. And it may be thatOnChange
is more appropriate because pressing a key is not the only way to get text into an edit control.By the way, it's better to ask one question at a time here on Stack Overflow.
用于将字符串类型值复制到字符数组类型值的快速方法。我建议使用这样的小辅助函数:
每次调用它时,传入要复制的最大长度。请记住,如果缓冲区长度为 15,则应传入 14 作为 maxlen,以便为终止 nul 字符留出空间(如果您打算始终终止字符串):
此函数将确保复制到记录中的数据以空终止,假设这就是您想要的。请记住,在固定长度字符数组中,由您决定规则是什么。空终止?完全用空格或空字符填充......字符串和字符数组是如此不同,以至于存在多种可能的方式在两者之间进行转换。
如果您不打算用 nul 终止字符串,那么您应该使用其他人的答案中显示的 FillChar+Move 组合。
For a quick way to copy string-type values into array-of-character type values. I suggest a small helper function like this:
Each time you call it, pass in the maximum length to be copied. Remember that if the buffer length is 15, you should pass in 14 as the maxlen, so that you leave room for the terminating nul character, if you intend to always terminate your strings:
This function will ensure that the data you copy into the record is null terminated, assuming that's what you wanted. Remember that in a fixed length character array it's up to you to decide what the rules are. Null terminated? Fully padded with spaces or null characters.... Strings and arrays-of-characters are so different, that there exist multiple possible ways of converting between the two.
If you don't intend to terminate your strings with nul, then you should use the FillChar+Move combination shown in someone else's answer.
显而易见的答案是当然。
不要使用压缩的字符数组。
请改用字符串。
如果您使用
ansiststring
,1 个字符将始终占用 1 个字节。如果您使用
shortstring
同上。Ansistring 与 Pchar 兼容,Pchar 是指向 char 压缩数组的指针。
所以你可以写
一些建议
看起来您正在将代码从 c 转换为 Delphi。
char 压缩数组
与旧的 (1995)shortstring
完全相同,减去shortstring
开头的长度字节。我能想到使用
压缩字符数组
的唯一原因是当您从磁盘读取数据或从磁盘读取数据时,并且您有不想更改的遗留代码。我将保留遗留代码以从磁盘读取和写入,然后将数据传输到 ansisstring 中,并且从那里仅使用 ansisstring。
这太简单了,Delphi 为您做一切。
而且... ansisstring 速度更快,自动创建和销毁,可以具有任意长度(最多 2GB),使用更少内存 - 因为仅存储相同的字符串一次(这意味着
stringa:= stringb
,其中字符串为 20 个字符,使用 ansistrings 比使用 char 数组至少快 5 倍)。当然最重要的是,
ansiststring
不可能出现缓冲区溢出错误。unicodestring
怎么样?Unicodestring 很好用,但有时在
char 压缩数组
和 unicodestring 之间转换时会发生字符转换,因此我建议在这种情况下使用ansistring
。The obvious answer is of course.
Don't use a packed array of char.
Use a string instead.
If you use
ansistring
, 1 char will always take 1 byte.If you use
shortstring
ditto.Ansistring is compatible with
Pchar
which is a pointer to apacked array of char
.So you can write
Some advice
It looks like your are translating code from c to Delphi.
a
packed array of char
is exactly the same as the old (1995)shortstring
minus the length byte at the beginning ofshortstring
.The only reason I can think of to use
packed array of char
is when you are reading data to and from disk, and you have legacy code that you don't want to change.I would keep the legacy code to read and write from disk and then transfer the data into an
ansistring
and from there on only useansistring
.It's soooooooo much easier, Delphi does everything for you.
And...
ansistring
is much faster, gets automatically created and destroyed, can have any length (up to 2GB), uses less memory --because identical strings only get stored once (which meansstringa:= stringb
where a string is 20 chars is at least 5x faster using ansistrings than array's of char).And of course best of all, buffer overflow errors are impossible with
ansistring
.What about
unicodestring
?Unicodestring is fine to use, but sometimes translation of chars happens when converting between
packed array of char
and unicodestring, therefore I recommend usingansistring
in this context.实际上,您尝试做的事情是不可能的:
尝试将指针(StrPLCopy 的结果,Delphi 的最后几个版本中的 PWideChar)分配给数组,这确实是不可能的。你不能像这样复制一个数组。我会这样做:
这应该可行,并且在我看来,这是将字符串复制到字符数组的最简单的解决方案。没有必要使用 a 作为某种中间体,并且使用 Move 在我看来是相当低级的,因此有点棘手(很容易忘记乘以字符的大小,它是未经检查的,它不会添加 #0 等),尤其是当您不知道自己到底在做什么时。
该解决方案甚至适用于 Delphi 2009 之前的 Delphi 版本,因为它不依赖于字符的大小。
FWIW,我不会使用打包数组。 Packed 在当前的 Delphi 中没有意义,但可能会混淆编译器并使类型不兼容。
What you try to do is impossible, indeed:
That tries to assign a pointer (the result of StrPLCopy, a PWideChar in the last few versions of Delphi) to an array, which is indeed impossible. You can't copy an array like that. I would do:
That should work, and is IMO the simplest solution to copy a string to an array of characters. There is no need to use a as some kind of intermediate, and using Move is, IMO, rather low level and therefore a little tricky (it is easy to forget to multiply by the size of a character, it is unchecked, it does not add a #0, etc.), especially if you don't know what exactly you are doing.
This solution should even work for versions of Delphi before Delphi 2009, as it does not rely on the size of the character.
FWIW, I would not use packed arrays. Packed doesn't have a meaning in current Delphi, but could confuse the compiler and make the types incompatible.