张志峰的博客

水滴石川,积少成多。

导航

delphi pchar char byte string转换问题

Posted on 2011-11-23 16:30  ╰★张志峰★╮  阅读(13649)  评论(0编辑  收藏  举报

delphi pchar char byte string转换问题
注:Delphi中的Char,PChar,PByte,Byte,String的相互转换,您是不是也遇到过,为此头疼过吗?你要是明白了他们的原理就会轻松了。

话题064840的标题是: Q:关于PChar的用法 (200分)
分类:非技术问题 PTiger (1998-10-19 18:33:00)
我要从tPing.ini中读取Host段中的Address键值,但是读不出。
1、首先往tPing.ini中写数据
host := '8.8.8.8';
WritePrivateProfileString(
'Host', 'Address',
PChar(host), 'tPing.ini');
发现C:\WINDOWS\tPing.ini文件中已成功写入如下内容:
[Host]
Address=8.8.8.8
2、读取数据
var
pAddress: PChar;
str: String;
acAddress: array[0..20] of Char;

GetPrivateProfileString(
'Host', 'Address', '127.0.0.1',
pAddress, //这里改为PChar(str)也不行,用acAddress可以
20, 'tPing.ini');
但用就acAddress可以,不知为何?请问PChar与Char数组、String的用
法有何区别?如果用PChar和String,分别如何实现?
请赐教!先说谢了!
 
tqz (1998-10-19 18:38:00)
你这里的pAddress还没有分配内存呢!
在GetPrivateProfileString前面加入:
pAddress:=StrAlloc(20);
使用完pAddress之后要释放掉:
StrDispose(pAddress );
 
曹晓钢 (1998-10-19 18:46:00)
或许这是你想要的:
var INI:TINIFile;

begin
INI:=TiNIFile.create('c:\tPing.ini');
INI.ReadString('HOST','Address','0.0.0.0');

定义是:
function ReadString(const Section, Ident, Default: string): string;
procedure WriteString(const Section, Ident, Value: string);
 
dwwang (1998-10-19 18:49:00)
PChar是指针,这一点上与C相同,因此你要使用(写)
它,必须事先申请内存.你的程序直接用pchar,
没有申请内存,因此肯定不行;相反,char数组是可以的.

pchar与char数组可以直接转换,例如:你的程序里先写:
pAddress:=@acaddress,然后再使用pAddress就可以成功了.
或者用tqz的方法直接分配内存是一样的.

StrPas和StrPCopy可以用来转换pchar与string,
在你的程序里,读出数据后,用str:=strpas(pAddress)
转换就可以了.
 
O_O (1998-10-20 0:59:00)
不知你用的Delphi是多少版本,2.0以上,将str定义为AnsiString,则可用pchar转换
 
柳五公子 (1998-10-22 14:17:00)
1. String是Pascal使用的字符串格式.它分为ShortString,
WideString和AnsiString,String缺省为AnsiString.
ShortString的最大长度为255个字符.
AnsiString 的最大长度为2^31个字符.
WideString 的最大长度为2^30个字符.
AnsiString和WideString的区别在于字符集的不同.
AnsiString对应于AnsiChar,WideString对应于WideChar.
具体你可以参考Delphi Help中String Type帮助.

2. PChar是Delphi为了和C语言的字符串类型(char *)兼容,
以便调用Windows API而建立的数据类型.所以pchar实际是
一个指针.一般使用方法是:
pchar eg1;
GetMem(eg1,Size); //你程序中出错就是因为没有为它分配内存
...
FreeMem(eg1,Size);
你还可以用以下方法;
eg2 :array[0..Size] of char;
然后可以把eg2看作pchar来用,且它已预先分配了内存.
要注意的是定义eg2的字符数组下界必须是0 !否则将会出现错误.

3. 在Delphi 1.0中的String和PChar的相互转换为:
function StrPas(str :pchar):string;
function StrPCopy(Dest:Pchar;Source:string):pchar;
在Delphi 2.0和更高版本中的String和PChar的相互转换很简单:
String ->Pchar: pch :=Pchar(str) ;
Pchar ->String: str :=pch;

4. String和pchar的内存实现方法略有不同(虽然他们实际上都是指针),
所以你的例程中不能用pchar(str)来将返回值强制放入str中,而要首先
用一个pchar型变量获得返回值(首先需为其分配内存),然后用
str:=pAddress转换为string型放入str中.
###
 
aimingoo (1998-10-23 8:05:00)
天啊!!这个问题居然还没有收场???我本来这些天不打算在这儿回答问
题,因为我在做我的MainPage,更糟糕的是,我的系统受到网络Hacker攻击,
Format C:了。忙于整理系统的时候,还是被这200分给吸引了,毕竟,有银
子可拿是无比爽快的事啊!

======================================
1. 如果你的确可以用 acAddress: array[0..20] of Char;来传参数,那
么就可以肯定,你没有为pChar分配内存。
2. GetPrivateProfileString()的第四个参数是lpReturnedString,用于
返回结果串。如果你没有给这个LPTSTR(Delphi中用pChar)分配内存,则返
回为空,如果分配内存不足,将导致结果串不全。
3. 问题是为什么呢?pChar的定义只是一个Pointer!!这意味着,除一个地
址外,pChar本身不用于存放任何东西,也不存放字符串。要不你用sizeof(pChar)
看看就明白了。那可只有4个byte呀!!

4. 那么,pChar的字符串在那儿呢?它事实上被存放在以pChar指向的一个
不定长内存块中。以#0为这个串的结束标志。如果没有特殊指定,Windows
只在找到#0时就认为串结束,而不会如得到一个你所期望的字符串。

5. 我们致少有以下三种解决方法:
(1)在使用pAddress前分配内存,使用后释放内存。
StrSize := 20;
GetMem(pAddress,StrSize);
... //GetPrivateProfileString()调用
FreeMem(pAddress,StrSize);
(2)使用字符数组
const StrSize = 20;
var pAddress : pChar;
chrArr : Array [0..StrSize] of Char;
begin
...
pAddress := @chrArr;
... //GetPrivateProfileString()调用
end; //这种用法中,Delphi会自动释放掉chrArr所用内存
(3) 直接使用字符串
在Delphi 3及以上版本中,支持Huge String,你可以直接将String
用成pChar(D2是否可以,我没有试过)。但是,你也要先给String指定一个长度。如下:
var sAddress : String;
StrSize : Integer;
begin
StrSize := 20;
SetLength(sAddress,StrSize);
GetPrivateProfileString('Host', 'Address', '127.0.0.1',
pChar(sAddress), StrSize, 'tPing.ini');
end;

6. 关于建议:
在上述三种方法中,第一种最安全,第三种是最方便的(因为你可以有一个
动态的buffer,并且,可以象String一样方便的用它),我推荐使用第三种方法。
WritePrivateProfileString()中的使用同上。但如果你采用第三种方法,
则只需要将字符串写到Host串中,用pChar(Host)作为入口参数就成了。不需要
再用SetLength()来指定串长。
使用第三种方法如果编译时提示字符串类型转换错误,则是因为你没有将"Huge
String"编译选项打开,可使用{$H+}编译符指定,或设置Project的Option


------------------------------------------

在delphi中Char,PChar,PByte,Byte,String的相互转换示例:

var
s:string;
pc:pchar;
pb:pbyte;
ac:array[1..100] of char;
ab:array[1..100] of byte;
i:integer;
begin
s:='this is a test';
pc:=pchar(s); //string->pchar
pb:=pbyte(pc); //pchar->pbyte
for i:=1 to length(s) do
begin
ac[i]:=s[i]; //string->arrary of char
ab[i]:=byte(s[i]); //string->arrary of byte
end;

s:=pc; //pchar->string
s:=string(pb); //pbyte->string
s:=c; //arrary of char->string;

end;
------------------------------------------------------

barton:

虽然这个问题很简单,但其实很不人并不完全清楚。

1.ShortString最大长度是由程序员指定的,但最多255个字符是不错。问题
是Delphi在处理时有很大不同。ShortString可以用Str[0]取字符串长。在
申请局部变量或者传递参数时ShorString在堆栈段分配空间,而其它类型的
串是在堆中;如:MyStr: string[48];在堆栈段分配52字节空间存放一个短
串。

2.String分配和释放由Delphi去优化,你不用关心是否会造成内存泄漏。在每
一个String变量前都有详细的RTTI去管理它。AnsiString和WideString其实
和String在使用时是一样的,因为Delphi并未为AnsiString和WideString建
立特殊的函数。传递参数时是一个地址。例如将流中的数据读到一个String
中,应该按下列方式操作:
SetLength(Result, Count); //相当于分配空间
Stream.Read(Result[1], Count); //读数据到串

3.PChar类型纯粹为兼容C和WindowsAPI而设,使用非常麻烦。
APChar := StrAlloc(n); -- 分配空间
StrDispose(APChar); -- 释放空间
当然是以地址来传递的。