关于Pchar指针的使用(30分)

  • 主题发起人 主题发起人 ddzhouqian
  • 开始时间 开始时间
D

ddzhouqian

Unregistered / Unconfirmed
GUEST, unregistred user!
实现功能如下:
有一字符串,转换成pchar类型后,做如下处理:判断每个字符的是否是我需要的.
大致代码如下:
procedure TForm1.Button3Click(Sender: TObject);
var s1:String;
p1:Pchar;
begin
s1:='0123AB';
GetMem(p1, sizeof(char) * length(s1));
p1:=PChar(s1);
while p1<>nil do
begin
if p1^ in ['0'..'9','a'..'f','A'..'Z'] then
begin
showmessage('ok');
end;
inc(p1)

end;
FreeMem(p1);
end;
我现在的结果是返回的次数已经超过了s1的长度,是不是我没加结束符号啊?可我申请了内存空间了啊.不懂,求知人告知,多谢!
 
结束号是不是nil
循环到第几个出错?
 
没有出错,只是一直在循环,我只是要检索完'0123AB'就好了,现在是指向到'B'后,p1仍然有值,很奇怪,我知道是我用的不对,就是找不到原因.
 
用for循环,控制循环次数:
while p1<>nil do
begin
if p1^ in ['0'..'9','a'..'f','A'..'Z'] then
begin
showmessage('ok');
end;
inc(p1)

end;
-------------------------
for i := 0 to length(s1) - 1 do
begin
if p1^ in ['0'..'9','a'..'f','A'..'Z'] then
begin
showmessage('ok');
end;
inc(p1)

end;
 
Delphi对于动态数组不会判断是否越界(PChar也相当于一个动态数组),所以过界不会产生异常,但是你取的数据实际上是别的数据,可能是空内存块的,也可能是分配给其它变量的内存。
 
楼上的解答正确,
while p1<>nil do一直没满足,
一直在往更深的内存中走,边走边取,直到取到一个nil为止。
 
to moolleychean:
那如果是如你说的,那我可不可以申请内存呢,只对申请的内存的进行处理呢?
GetMem是不是就是这个意思呢?
 
楼主这样的写法错误很多:
错误1. GetMem(p1, sizeof(char) * length(s1))
// 分配的内存不够, 要保存一个字符串, 最少需要字符串的长度+1个字节
道理要你自己慢慢体会;
错误2. Delphi中的变量(或者内存)一般不会自动清零的, 需要对GetMem后的p1清空;
错误3. while (p1 <> nil) 的写法是错误, 永远没有结尾
楼上有人的说法是错误的, 永远走不到nil, 内存地址本身没有nil的...可能比较难理解吧...
错误4. 执行inc(p1)移动p1的指针位置后, 再执行FreeMem(p1)是严重错误的行为;

要改写你的代码很难, 其实最简单一个办法是使用&quot;栈&quot;而不是使用&quot;堆&quot;做一些简单事情, 例如: 这样写:
procedure TForm1.Button3Click(Sender: TObject);
var s1:String;
p1:array[0..127] of char
// 使用栈, 不用getmem与Freemem
i : integer;
begin
s1:='0123AB';
fillchar(p1, sizeof(p1), 0)
// 最好这样做
strpcopy(p1, s1)
// 复制
i := 0;
while p1 <> #0 do // 不是nil
begin
if p1 in ['0'..'9','a'..'f','A'..'Z'] then
begin
showmessage('ok');
end;
inc(i);
end;
end;

// 其实在这个例子中, 使用string本身就可以了, 为什么一定要用pchar呢?
// 以下是一个不是很安全的写法
var s1:String;
p1:pchar;
begin
s1:='0123AB';
p1 := pchar(s1);
while p1^ <> #0 do // 不是nil
begin
if p1^ in ['0'..'9','a'..'f','A'..'Z'] then
begin
showmessage('ok');
end;
inc(p1);
end;
end;
 
楼上高手,学习
 
New GetMem AllocMem 的区别
New 给一个结构申请内存。
new分配的指针一般这样定义
pCount: ^Integer
(或PInteger)
pnid: ^TNotifyIconData
(或PNotifyIconData)
然后在使用时直接 new(pCount)就可以了

而Getmem通常可以给任意的指针分配你想分配的内存大小
Getmem(pCount, SizeOf(Integer))

如果无类型指针,则必须用Getmem 如
p:Pointer

Getmem(p, 20);给p分配20个字节的内存空间
AllocMem 是在GetMem 的基础上,将申请到的内存初始化。
 
为什么p1要定义为Pchar? 定义为char不方便很多?
procedure TForm1.Button3Click(Sender:TObject);
var
s1:string;
p1:Char;
i:integer;
begin
s1:='0123AB';
for i:=1 to Length(s1) do
begin
p1:=s1;
if p1 in ['0'..'9','a'..'f','A'..'Z'] then
begin
ShowMessage('ok');
end;
end;
end;
 
谢谢各位,问题是解决了,还是有些模糊,我在看看书了!
1.to:新世纪
非常感谢指出那么多错误.其实我要的就是这个效果,因为很多东西比较含糊.
呵呵
2.如果用字符串str是可以,也很容易处理,而且代码也有较高的易读性,但据说用指针的话,速度会快些的,忘记是谁说的了,也可能代有一些潜意识吧.
3.各位的答案基本都是可以解决我的问题的,分怎么给挺麻烦的,我就随意给了,不好意思,呵呵
 
多人接受答案了。
 
后退
顶部