Q:关于PChar的用法(200分)

P

PTiger

Unregistered / Unconfirmed
GUEST, unregistred user!
我要从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,分别如何实现?
请赐教!先说谢了!
 
你这里的pAddress还没有分配内存呢!
在GetPrivateProfileString前面加入:
pAddress:=StrAlloc(20);
使用完pAddress之后要释放掉:
StrDispose(pAddress );
 
或许这是你想要的:
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);

 
PChar是指针,这一点上与C相同,因此你要使用(写)
它,必须事先申请内存.你的程序直接用pchar,
没有申请内存,因此肯定不行;相反,char数组是可以的.
pchar与char数组可以直接转换,例如:你的程序里先写:
pAddress:=@acaddress,然后再使用pAddress就可以成功了.
或者用tqz的方法直接分配内存是一样的.
StrPas和StrPCopy可以用来转换pchar与string,
在你的程序里,读出数据后,用str:=strpas(pAddress)
转换就可以了.
 
不知你用的Delphi是多少版本,2.0以上,将str定义为AnsiString,则可用pchar转换
 
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中.
###
 
天啊!!这个问题居然还没有收场???我本来这些天不打算在这儿回答问
题,因为我在做我的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。
 
Hi PTiger,
针对你的问题最好使用TIniFile对象, 如曹兄所说的。在创建对象时一般不需要
给出路径,如果想给出路径的话可以在文件名前面加上程序所在路径。注意如果
INI文件不存在的话读写时会出错,下面的代码检查INI文件是否存在,如果不存在
则创建一个新文件,实例如下:
procedure TSysConfig.FormCreate(Sender: TObject);
var
Inifile: TIniFile;
IniFilePath: array [0..156] of char;
IniFileName: string;
f: TextFile;
begin
GetWindowsDirectory(IniFilePath,156);
//如果不用Windows目录,可以用下一行替换上一行
//IniFilePath:=ExtractFilePath(Application.ExeName);
IniFileName:=IniFilePath+'/TPing.ini';
if not fileExists(IniFileName) then
begin
AssignFile(F, IniFileName);
rewrite(f);
writeln(f,'');
closefile(f);
end;
IniFile:=TiniFile.create(IniFileName);
IniFile.ReadString('HOST','Address','127.0.0.1');

iniFile.free;
end;
 
it seems that this question has been solved.
i have nothing else
to add.
 
多人接受答案了。
 
这个问题早该结束了,同时也试一下
给这么多人加分是什么效果 :)
 

Similar threads

D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
740
DelphiTeacher的专栏
D
顶部