delphi中move 和 strpcopy区别
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了delphi中move 和 strpcopy区别相关的知识,希望对你有一定的参考价值。
lstr := 'come on!123';Move(lstr, Data, Length(lstr));StrPCopy(@data[0], 'come on!123');结果差别很大,求教
string保存具体字符的内存对用户其中存放连续的字符。是透明的, 由Delphi管理它的分配, 复制和释放, 用户不能干预(其实也可以, 不过是通过非法途径)。
Move(ABuffer^,P^, Sizeof(TArrayByte))。
Move(ABuffer^,P^, Sizeof(TArrayByte)); //复制内存块。 参考技术A var
lstr:PAnsiChar;
data:PAnsiChar;
begin
lstr := 'come on!123';
Move(lstr, Data, Length(lstr));
ShowMessage(data); lstr := 'come on!123';
GetMem(data,length(lstr));
StrPCopy(data,lstr);
ShowMessage(data);
end; 参考技术B 1)Move是复制byte,用Length来计算字符串的长度的时,有可能不准确。
在Delphi 2010 的情况下,Length('中国'),长度为2,但是其实是4个Byte,复制就会丢失。
例如:
var
lstr: AnsiString;
PStr: array [0 .. 20] of AnsiChar;
begin
lstr := 'come,1234';
Move(lstr[1], PStr, Length(lstr));
ShowMessage(PStr);
end;
2)StrPCopy是复制一个AnsiString 或 WideString到PAnsiChar 或 PWideChar,不会做长度检查.
var
Data: PAnsiChar; //这是一个指针
begin
GetMem(Data,20);
StrPCopy(Data, 'come on!123');
ShowMessage(Data);
FreeMem(Data);
//也可以这样
Data:=PAnsiChar('come on!123');
end;
String[255]在高版本Delphi里还是被解释成Byte,总体长度256,使用StrPCopy可以给Array String拷贝字符串
学了好多不了解的知识:
procedure TForm1.Button1Click(Sender: TObject); var s1 : String; s2 : String[255]; begin s1:=‘ç1很好‘; ShowMessage(s1); // 这里显示正常 s2:=s1; ShowMessage(s2); // 这里显示乱码。 // 问这个问题的原因是,在一个recode pack 里定义了String[255],但是使用Unicode字符给它赋值的时候,就乱码了,这该怎么办? // 原因是String[255]还是被翻译成单字节字符,即使在Delphi 2010里也是如此 // 有没有办法定义一个类似 s2: UnicodeString[255]; 或者s2: WideString[255]这样的东西,好放在record里面使用 end; procedure TForm1.Button2Click(Sender: TObject); var S: ShortString; { 255个字符长度,256个字节} S1: String[255]; { S1和S的字符类型一样,通过使用String声明字符串并且在String后面用中括号规定字符个数的形式定义字符串} Len: Integer; begin S := ‘Hello‘; Len := Ord(S[0]); { Len现在包含S的长度为5,Ord函数可以把一个字符类型转换为整数类型} ShowMessage(IntToStr(Len)); Len := SizeOf(S); { Len现在包含的是ShortString类型的大小,为256字节,并不是字符串的长度} ShowMessage(IntToStr(Len)); ShowMessage(IntToStr(Length(s1))); end; procedure TForm1.Button3Click(Sender: TObject); var DirName :Array [0..255] of Char; myname : String; begin myname := ‘very good‘; // DirName := myname; // 这里赋值通不过 // DirName := PChar(myname); // 这里赋值通不过 // PAnsiChar StrPCopy(PAnsiChar Dest, const AnsiString Source); // PWideChar StrPCopy(PWideChar Dest, const UnicodeString Source); StrPCopy(dirname, myname); // ShowMessage(DirName); // 这样才可以 end; procedure TForm1.Button4Click(Sender: TObject); var S: ShortString; S1: String[255]; begin S := ‘Hello‘; ShowMessage(IntToStr(Length(s))); ShowMessage(IntToStr(Length(s1))); // 这里显示内容不定,因为S1没有进行初始化 end; procedure TForm1.Button5Click(Sender: TObject); var S: ShortString; S1: String[255]; // String[255]的长度,不乘以2。它还是会被翻译成Byte S3: String; S4: Array [0..255] of Char; // 并没有在前后预留什么空间 begin S := ‘Hello‘; ShowMessage(IntToStr(Length(s))); // 5 PWord(@S)^ := 100; ShowMessage(IntToStr(Length(S))); // 100,因为自动管理的长度值被改了 PWord(@S1)^ := 200; ShowMessage(IntToStr(Length(S1))); // 200,因为自动管理的长度值被改了 SetLength(S3, 255); ShowMessage(IntToStr(SizeOf(s))); // 256,之所以多了1,是因为有长度管理 ShowMessage(IntToStr(SizeOf(s1))); // 256,之所以多了1,是因为有长度管理(还是最后一个字符是#0?不太可能) ShowMessage(IntToStr(SizeOf(s3))); // 4 ShowMessage(IntToStr(SizeOf(s4))); // 512 ShowMessage(s4); // 内容不定,因为没有初始化 end; // 删掉Array里的某个字符,相当于Delete函数 procedure ArrayDelete(var pArray: array of Char; const nIndex, nCount: Integer); begin // Move ( const SourcePointer; var DestinationPointer; CopyCount : Integer ) ; Move(pArray[nIndex + nCount], pArray[nIndex], (StrLen(pArray) - nCount + 1) * SizeOf(Char)); end; procedure TForm1.Button6Click(Sender: TObject); var a: array[0..255] of Char; begin a := ‘123456789‘; ArrayDelete(a, 2, 3); ShowMessage(a); end;
lstrcpy
你也可以用windows单元里的lstrcpy函数。
这个是windows提供的等价strcpy的函数。
性能比strcpy低,但是有异常处理。
------------------------------------------------
var
DirName : String[255]
begin
// 若干赋值
Delete(DirName, Length(DirName), 1);
end;
现在改成:
var
DirName : Array [0..254] of Char
begin
// 这个Delete应该怎么写?没有初始化的字符,默认都是#0?
end;
比方说S1是Array [0..255] of Char
目前S1的值是MyName
我就是想把最后一个字符去掉,改成MyNam
------------------------------------------------
应该是错误的办法:
move(a[1], a[0], strlen(a)*sizeof(char));
去看tlist的delete方法
可能的办法:
a[5] := 0;
聪明办法:
procedure ArrayDelete(var pArray: array of Char; const nIndex, nCount: Integer);
begin
Move(pArray[nIndex + nCount], pArray[nIndex], (StrLen(pArray) - nCount + 1) * SizeOf(Char));
end;
var
a: array[0..255] of Char;
begin
a := ‘123456789‘;
ArrayDelete(a, 2, 2);
ShowMessage(a);
end;
笨办法:
mystring:=DirName;
mystring:=LeftStr(mystring, Length(mystring)-1);
StrPCopy(DirName, mystring);
------------------------------
疑问:
1. Array数组没有用完的时候,后面的字符会被初始化成什么?什么才是字符串准确终止?
2. String可否包含#0?应该可以。另外要学会使用String的头部数据。
3. 据说AnsiString和UnicodeString可以相互赋值
4. move只是移动内存数据 不会覆盖不被移动的区域
那a这个array是如何感受到,它的字符串变短了呢?
array不是有一个前缀,这样才能知道当前array用了多长的空间
学习了:
1. 新学了StrLen、Delete函数
2. 移动开发,String下标从0开始
--------------------------------
procedure TForm1.Button7Click(Sender: TObject);
var
S1: Array [0..255] of Char;
S2: String[255];
begin
S1:=‘0123456789‘;
S1[3]:=#0;
ShowMessage(String(S1)); // 012,我估计是转换到String的时候,碰到#0就停了。但其实S1的长度仍是10
S2:=‘0123456789‘;;
Byte(S2[0]) := 3;
ShowMessage(String(S2)); // 012,修改S2的长度管理,人工强行变成只使用了3个字符。
end;
这说明,array看到#0就停止。String[255]则是有一个前缀在管理使用的长度
这样就截断字符串了,就是你说的Delete,而且不考虑删除中间
最后一个小小问题:Array有一个前缀来管理使用的长度吗?
回答:没有。但是array of Char又有了。
--------------------------------
type
T = packed record
A: char;
B: string[5];
end;
procedure TForm1.Button8Click(Sender: TObject);
begin
ShowMessage(IntToStr(SizeOf(T)));
end;
答案是8,即2+1+5
以上是关于delphi中move 和 strpcopy区别的主要内容,如果未能解决你的问题,请参考以下文章
临界区对象TCriticalSection(Delphi) 与 TRtlCriticalSection 的区别(转)
delphi中move函数的正确理解(const和var一样,都是传地址,所以Move是传地址,而恰恰不是传值)太精彩了 good
delphi char数组string和Pchar的相互转换