关于String向PChar转换的问题(28分)

  • 主题发起人 主题发起人 calman
  • 开始时间 开始时间
C

calman

Unregistered / Unconfirmed
GUEST, unregistred user!
首先假设我要调用一个函数f(),f()需要PChar类型的参数,处理结果由参数带回。类似GetComputerName()。如果我调用的形式必须为GetComputerName(PChar(str), ..),即将String类型强制转换为PChar类型。请问我如何能肯定GetComputerName不会为PChar(str)这个参数分配空间用以存储处理结果?所以我在调用之前是否需要SetLength(str, ...)?
再假设我要写一个函数f(p: PChar)被其他地方调用,处理结果由参数带回。在函数工作之前,我必须判断参数的有效性,如果调用者用f(PChar(str))的形式来调用我写的函数,请问我如何能肯定p是否已经被分配了空间?
 
看的不太懂,STRING和PCAHR。
 
是我说得不清楚吗?
 
var
s:string;
p:pchar;
begin
s:='qqqq';
p:=pchar(s);
s:=string(p);
end;
 
不太懂你的意思
在我理解pchar 实际上是一个指针 ,pchar(s)的作用是把s+null 然后把指针指向第一个字符,而字符串一般是不要分配内存的,它是自动分配,自动管理的.
 
strpcopy也能转换
 
第一,我需要通过地址转递的形式(非值传)将一个参数传给一个函数,这个函数将处理结果存放在此参数所指向的地址中返回给调用者,类似GetComputerName()。
有两种方法,第一是在调用之前为实参分配空间(若实参是String则SetLength,若实参是PChar则AllocMem),我的实参用的是String类型,通过强制转换去调用函数,问题是我不知道类似GetComputerName这样的函数是否会再为参数分配空间!
多数函数不会,如果遇到这种情况,它可能会触发一个异常或返回一个错误码。但假设,我正在编写一个类似GetComputerName()的函数,我如何知道传递来的参数是否已分配了空间,如果以分配,我便让函数继续执行;否则触发一个异常或者其他操作。
正因为String类型是被自动管理的,所以在转换过后如何来判别它的空间是否有效呢?
 
或者这种调用规则本身就是不规范的,让人搞不懂的,所谓后现代的。。。
但确实是很方便的[:D]
 
应该也是由系统自动管理,不用自己操心。长度可能有个上限(系统内定的)
 
procedure TForm1.MyFunc(p1, p2: PChar);
begin
StrCopy(p1, '1');
StrCopy(p2, '2');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
str1, str2: String;
begin
SetLength(str1, 2);
SetLength(str2, 2);
// str1 := '1';
// str2 := '2';
// Caption := str1+str2
= 12 显示12
MyFunc(PChar(str1), PChar(str2));
Caption := str1+str2
只显示1
end;

书上说在StrUtils有一个RealizeLength()函数可以恢复String原来的长度,但我用的是D6,没有这个函数,怎么解决呢
 
你是在开发指南看到这个函数的把
SetLength(str1,strlen(pchar(str1)))//用它
 
那请问第一个问题该怎么理解呢?
 
等了一天,也许真的没有办法了
 
我来告诉你

第一是在调用之前为实参分配空间(若实参是String则SetLength,若实参是PChar则AllocMem),我的实参用的是String类型,通过强制转换去调用函数,问题是我不知道类似GetComputerName这样的函数是否会再为参数分配空间!
函数之间的调用,参数的用法必须明确,如果GetComputerName这样的函数会再为参数分配空间,你传PChar过去有什么用?如果你不为PChar分配空间,GetComputerName拿了PChar又怎么用呢,总的来说,你必须清楚函数怎么用才能调用它(参数是其中的一部分)

但假设,我正在编写一个类似GetComputerName()的函数,我如何知道传递来的参数是否已分配了空间,如果以分配,我便让函数继续执行;否则触发一个异常或者其他操作。

答案同上

解决办法
如果函数都在DELPHI中调用,那非常简单
procedure TForm1.MyFunc(var s1, s2: string);
begin
s1:='1'
//StrCopy(p1, '1');
s2:='2'
//StrCopy(p2, '2');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
str1, str2: String;
begin
// SetLength(str1, 2);
// SetLength(str2, 2);
// str1 := '1';
// str2 := '2';
// Caption := str1+str2
= 12 显示12
// MyFunc(PChar(str1), PChar(str2));
MyFunc(str1,str2);
Caption := str1+str2
只显示1
end;


 
“如果GetComputerName这样的函数会再为参数分配空间,你传PChar过去有什么用?如果你不为PChar分配空间,GetComputerName拿了PChar又怎么用呢”
我知道,PChar仅仅是一个指针,本来通过指针来传递参数并没有不对的;只是因为有了String类型,而且这个类型很特别,String之间的赋值或参数传递我是清楚的,单纯PChar之间的参数传递我觉得也没有什么,和C中的char *没有什么区别吧~
但问题在于将String类型强制转换为PChar后,再调用PChar类型参数的函数,这样问题就来了
======
function TForm1.MyFunc(p: PChar): Boolean;
begin
Result := false;
if p = nil then //不管它指的对不对,至少不能为空吧
Exit;
StrCopy(p, '1');
Result := true;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
p: PChar;
s: String;
b: Boolean;
begin
p := nil
//
b := MyFunc(p)
//正确
//???
//b := MyFunc(PChar(s));
//这样调用MyFunc,怎样让MyFunc可以做合法性的检查?在???可以对s做些什么呢?
if b then
......
end;
===
我的意思就是想在编程序的时候更安全一点,最怕我写的模块在我的机器上一切OK,但一到别人机器就歇菜~~~
 
这样即可:
s := '';
b := MyFunc(PChar(s));
这样在 MyFunc 里面的 p 会被判断为 nil,所以安全。
 
我明白你的意思,但是我仍然觉得你过虑,
function TForm1.MyFunc(p: PChar): Boolean
既然需要一个PChar的参数,调用者自然要负责PChar的分配与释放 MyFunc 中能做的不多,而且你不能预期别人程序中的BUG
 
多人接受答案了。
 
后退
顶部