将字符串分配给字符数组

时间:2011-04-28 18:09:57

标签: delphi

问题一

我有

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

5 个答案:

答案 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参数,只需提供任何内容,例如Selfnil

问题三

考虑以下代码:

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中没有意义,但可能会混淆编译器并使类型不兼容。