关于delphi指针移动的问题(100分)

  • 主题发起人 主题发起人 smzgl
  • 开始时间 开始时间
S

smzgl

Unregistered / Unconfirmed
GUEST, unregistred user!
有个奇怪的问题,意图如下:通过移动指针,来实现修改字符串.例如:把0123456789,修改为01234ABCDE代码如下:

var
p,pp: Pointer
begin
GetMem(p,10);
PChar(p^):='0123456789';
Label1.Caption := PChar(p^);
pp:=p;

Inc(Char(pp^),5);

PChar(pp^):='ABCDE';
Label2.Caption := PChar(pp^);

Label3.Caption := pchar(p^);
end;

运行结果如下:
Label1显示 0123456789
Label2显示 ABCDE
Label3显示 ABCDE

发现问题没有? 用Inc移动指针后,再进行修改,结果,整个指针的内容都变了.跟踪进去看,发现其实在Inc之后,pp的指针地址并没有改变.

那我应该如何实现阿.
 
你测试这样的试试看?
var
p,pp:Pointer;
begin
GetMem(p,10);
PChar(p^):='0123456789';
Label1.Caption:=PChar(p^);
pp:=p;

Inc(char(pp^),5);

// PChar(pp^):='ABCDE';
Label2.Caption:=PChar(pp^);

Label3.Caption:=PChar(p^);
end;
 
Inc(Char(pp^),5);
此时:pp^为 '0123456789'
char('0123456789') 为 ‘0’
inc('0',5) 相当与 inc(chr('0'),5)
由上和pp p 的值有和关系? 他们还是没动过!
此时 Label2.Caption:=PChar(pp^)
会显示 ‘5123456789’
 
这样试试:

var
p,pp: Pointer
begin
GetMem(p,10);
PChar(p):='0123456789';
Label1.Caption := PChar(p);
pp:=p;

Inc(PChar(pp), 5);

PChar(pp):='ABCDE';
Label2.Caption := PChar(pp);

Label3.Caption := pchar(p);
end;
 
我已经实现了你要的结果
var
p, pp: PChar;
str: ShortString;
i: Integer;
begin
GetMem(p, 10 * SizeOf(Char));
pp := p;
str := '0123456789';
for i := 0 to 10 do
begin
pp^ := Char(str[i + 1]);
Inc(pp);
end;
Label1.Caption := p;

pp := p;
Inc(pp, 5);
Label2.Caption := pp;
str := 'ABCDE';
for i := 0 to 4 do
begin
(pp)^ := str[i + 1];
Inc(pp);
end;
Label3.Caption := p;
end;
 
晕,老大,你指针用法错了........

错误1:
//跟踪进去看,发现其实在Inc之后,pp的指针地址并没有改变.
当然不会变啊...
你写的是Inc(char(pp^),5);....pp的地址是指针本身的地址,而你inc的是pp^,也就是pp指向的地址,也就是说是字符串'0123456789'的地址
你可以去看看,如果你在Inc(char(pp^),5);以后不执行
// PChar(pp^):='ABCDE';
Label2.Caption := PChar(pp^);
则label2显示的会是56789

错误2:你使用pp:=p;这样和没使用是一样的,没有为pp分配内存,所以pp无论是指针本身的内存还是指向的内存都是完全一样的
所以你在改了pp指针本身的值[red](Inc(char(pp^),5);这句,实际是修改指针本身存放指向内存的地址值,也就是修改指针本身的值)[/red]以后p的指针指向地址也会一起跟着变
如果你想修改pp的显示内容而p的显示内容不变,应该再为pp分配一块内存然后再把那些字符复制到新内存中

错误3:PChar(pp^):='ABCDE';这句本身没错...可是结合了错误2那就相当于把原来的'0123456789'的内存释放掉,而重新为'ABCDE'新申请了一块内存,然后再让pp指向改内存首地址(同时p也指向新字符串地址了)

错误4.....GetMem(p,10);
这句也不对,你的p是指针,所以申请内存应该申请指针实际类型需要的长度
也就是应该是GetMem(p,sizeof(pchar));或者这样写new(pchar(p));
为指针申请内存和那个字符串长度没关系

最后,也是我不理解的.......pchar本身就是指针,你直接把p认为是pchar不就行了
干吗还要吧p指向一个pchar指针然后再让pchar再指向一个字符串?
而你PChar(p^):='0123456789';这样等于把pchar指向了一个静态内存,这个内存里的字符是不能被改变的,所以你想把后面的56789改为ABCDE是不行了
你首先要把0123456789复制到你自己新申请的内存中,然后再修改

结合上面几个错误.....按照你最开始的要求,只是要修改字符,只用一个指针就够了
代码如下:
var
p: Pointer;
i:integer;
const
str='ABCDE';
begin
pchar(P):=StrAlloc(11)
//再为指针内存分配字符串内存
strpcopy(PChar(p),'0123456789')
//把静态内存里的字符复制到你刚申请的内存中
Label1.Caption := pchar(p);
Inc(pchar(p),5);
for i:=1 to length(str) do begin
char(pchar(p)^):=str
//修改内存中的字符
inc(pchar(p));
end;
char(pchar(p)^):=#0;
dec(pchar(p),length(str)+5)
//返回最开始的位置
Label2.Caption := pchar(p);
end;
 
指针很难啊
 
难吗? 不难吧........
 
我想要的不是复制字符串,而是截取字符串.例如,有"0123456789",现在要把"56789"修改成"ABCDE"

其实我目的是:分配一大块内存,然后自己按规格细分.
例如:getmem(p,100),把这100的空间平均分成10分,分别分给pa: array[0..9] of Pointer;
 
getmem(p,100)
for i:=0 to 9 pa:=P+i*10;
 
接受答案了.
 
后退
顶部