高分!关于字符串的操作,不是很难,可我想不过来了。 (50分)

  • 主题发起人 主题发起人 feng_me
  • 开始时间 开始时间
F

feng_me

Unregistered / Unconfirmed
GUEST, unregistred user!
[?]function GetLinkName(SourceStr: string): Pchar;
var
Name: array[0..100] of char;
i, len: integer;
TempStr:string;
begin
result:='';
for i := 1 to 100 do
Name := #0;
len := length(SourceStr);
Strpcopy(Name, SourceStr);
if Name[len] = '/' then
len := len - 1;
if len <> 2 then
begin
for i := len downto 1 do
if Name = '/' then
begin
showmessage(inttostr(i));
result:=Pchar(copy(Name, i + 2, len-i));
break;
end;
end;
end;

procedure TMainForm.Button2Click(Sender: TObject);
begin
edit1.Text:=GetLinkName('c:/kav');
end;

这本来是截取路径里最后一个目录(或文件)的名字的小程序,
但是如果使用‘c:/kav’等小于6个字符长的话,edit1就什么也不显示。
‘c:/kdjfasljkdlsajkfa;l’就可以显示出kdjfasljkdlsajkfa;l而且没有什么
错误。
我弄了很长时间,还是搞不懂。

本贴分数将献给告诉我原因或能给我通俗的(或例子)讲解几种字符串类型作用域的大侠。
 
我不明白,为什么你要写这样一个函数,Delphi中已经有这样功能的
函数了。

ExtractFilePath(文件名)

应该是这样的,你看看吧。
 
实际上以为了练手。
我的object pascal 不怎么样,练练。
谢谢。
不过您说的那个函数我也不会,能不能讲讲。
 
获取文件路径:
Returns the drive and directory portions of a file name.
Unit
Sysutils
Category
file name utilities
function ExtractFilePath(const FileName: string): string;
Description
The resulting string is the rightmost characters of FileName, up to and including the colon or backslash that separates the path information from the name and extension. The resulting string is empty if FileName contains no drive and directory parts.
Note: This function works for multi-byte character systems (MBCS).
 
把这段代码放到程序中看看。
Label1.caption:= ExtractFilePath(Application.ExeName);
 
应该是Pchar与string之间不兼容的问题造成的。
 
你的代码我执行了,没问题呀。
我也写了一段。不过可能有点罗嗦。
function TForm1.GetLinkName1(SourceStr: string): Pchar;
var
Name: array[1..254] of string;
i, len: integer;
TempStr1,TempStr2:string;
begin
TempStr1:=trim(SourceStr);
len := length(TempStr1);
For i:=1 to len do
begin
Name:=copy(TempStr1,1,1);
Delete(TempStr1,1,1)
end;
For i:=len DownTo 1 do
begin
if Name<>'/' then
TempStr2:=TempStr2+Name
else
break;
end;
Len :=length(TempStr2);
For i:=1 to len do
begin
Name:=copy(TempStr2,1,1);
Delete(TempStr2,1,1)
end;
TempStr1:='';
For i:=len DownTo 1 do
TempStr1:=TempStr1+Name;
result:=Pchar(TempStr1);
end;
 
to up:
谢了,csdn的大侠调试我的程序都说没问题,可是我的机器上就不可以。
你的代码我看了。可以使用。但是我想知道为什么我的不可以。
to lw86:
关于pchar和string和shortstring的区别(作用域)等等,您能说说?
 
我知道大概的原因了。
feng_me的代码中,如果是返回值大于3个字节时是正确的,这个涉及到了内存空间的分配
问题。当result的值小于4时,系统就不重新分配内存给result,而直接利用了局部变量name的
空间,这样返回值就是不定的。如果大于4,系统则从新给result分配空间,这样结果就是对的。
而ckylixj的代码中的name是用string,系统总会先分配内存给它,所以返回值也是对的(不论
值的长度大小)。

to feng_me:
如果你的函数改为:
function GetLinkName(var SourceStr: string): pchar;
~~~
...
if Name = '/' then
begin
SourceStr := copy(SourceStr,i + 2,Len - i);
result := Pchar(SourceStr);
break;
end;

应该是可以的。
 
to up:
不是很明白,您楼上那位的代码和我的没有什么区别。
您说的name是什么?形参?
他也没有用var 阿。
不过谢谢您了。
不知能不能发个给分的帖子。我想给这个帖子加分。
 
啊,编译通过了。
为什么能行呢?大哥给说说。
 
to Chenxz:
1)说法本身基本正确,但不是问题的症节所在;
2)实现方法完全正确;
to Feng_me:
 问题的关键是如何从函数内部返回指针,此处是字符指针(PChar);
 如果result指向的不是全局变量或传入的变参,则应为其在全局堆中分配内存,因为局部
变量都是在堆栈中分配的,从函数中返回后,堆栈自动清空,其结果是不定的。
 解决方案如下:
result:=Pchar(copy(Name, i + 2, len-i));
改为:
result:=StrNew(PChar(copy(Name, i + 2, len-i))); 
 
就是内存分配的问题。结束吧:)
 
不明白要这么复杂的,写成这样不是更好:
function GetLinkName1(const SourceStr: string): Pchar;
var
I, len: Integer;
begin
I:= Length(SourceStr) - 1;
repeat
if SourceStr = '/' then begin
Len:= length(SourceStr) - I;
GetMem(Result, len);
Dec(Len)
Inc(I);
Move(SourceStr, Result, Len);
PShortString(Result)^[Len]:= #0;
Exit;
end;
Dec(I);
until I = 0;
Result:= nil;
end;
 
多人接受答案了。
 
后退
顶部