delphi.指针.PChar

此文是delphi.指针.应用姊妹篇,想细化一下PChar应用,所以有了此文。

注意:

1:此文讲的是PChar与字符串相关操作,其它方法暂不多讲。

2:由于D分开Ansi/Unicode的两种完全不同的编绎器,即: Ansi.Char=AnsiChar; Unicode.Char=WideChar

所以在此文中,PChar针对于PAnsiChar, 对于PWideChar,需要做其它处理,请注意

PChar是一个指针,它指向了一个字符串内容的指针,与Pointer相比,它有数据类型(Char)。

所以,有人也喜欢拿它作为内存块的存储,进行一种Buffer的封装,因为它与Pointer相比,移动,转换方便,居家必备啊(请看用法二)

 用法一:

1 var
2   p: PChar;
3   s: string;
4 begin
5   s := ‘abc‘;
6   p := PChar(s);   

最常用的代码,进行string与PChar的数据类型转换,在各类API中,经常用到。

其它相关用法是:赋值时,进行移动:+-

p := PChar(s) + 1;                     // p 指向s[2]

p := PChar(s) - sizeof(Integer);  // p 指向string.len

注意:

string在其内容必定是Char = #0。即s := ‘abc‘; 在s 申请的(3 + 1) * sizeof(char),其中的1就是为#0准备的。

// ShowMessage(IntToStr(Ord((PChar(s) + Length(s))^)));

用法二: 用PChar进行缓存处理

 1 type
 2   PMyString = ^TMyString;
 3   TMyString = record
 4     buf: PAnsiChar;
 5     len: Integer;
 6     buf_len: Integer;
 7   end;
 8
 9 // 初始化+分配空间
10 procedure string_init(var s: TMyString; buf_len: Integer);
11 begin
12   FillChar(s, SizeOf(s), 0);
13   s.buf := AllocMem(buf_len);
14   s.buf_len := buf_len;
15 end;
16
17 // 反初始化+释放空间
18 procedure string_uninit(var s: TMyString);
19 begin
20   if s.buf_len > 0 then
21     FreeMem(s.buf);
22   FillChar(s, sizeof(s), 0);
23 end;
24
25 // 写数据(任意数据)
26 procedure string_write(var s: TMyString; buf: Pointer; len: Integer); overload;
27 begin
28   if len + s.len > s.buf_len then
29   begin
30     Inc(s.buf_len, len * 2);
31     ReallocMem(s.buf, s.buf_len);
32   end;
33   if len > 0 then
34   begin
35     Move(buf^, (s.buf + s.len)^, len);
36     Inc(s.len, len);
37   end;
38 end;
39
40 // 写数据(字符串数据)
41 procedure string_write(var s: TMyString; const AData: string); overload;
42 begin
43   string_write(s, PAnsiChar(AData), Length(AData) * sizeof(Char));
44 end;
45
46 // 读数据(只针对字符串),读完后清除数据
47 function string_read(var s: TMyString): string;
48 begin
49   if s.len > 0 then
50   begin
51     SetString(Result, s.buf, s.len);
52     s.len := 0;
53   end else
54     Result := ‘‘;
55 end;

以上是个简单的用PChar进行buffer缓存的函数,在写(string_write)的过程中,其实就是一个简单PChar的+-处理,只是一个延伸方法。

读操作,只写了个字符串,其它数据,如integer, double之类的,其实就是一个指针转换的问题,如:

1 result := PByte(s.buf)^;
2 result := PInteger(s.buf + 1)^;
3 result := PCardinal(s.buf + 1 + 4)^;
4 result := PDouble(s.buf + 1 + 4 + 4)^;
5 result := PMsg(s.buf + 1 + 4 + 4 + 8)^.wParam;

还有个操作是string_delete的,留着有兴趣的人自行处理:)

用法三:

不知是否看过代码:Classes.pas::TParser.NextToken,里面的代码,进行解析字符串写的非常有意思。

大概规则是:当遇到某需的字符,然后找到结束符,然后得到一个串,根据规则,让那个串转为integer, string...

然后,我就学会了用PChar去解析各类字串,我得说那代码得赞一个,思路非常有意思,建议一看。

下面例子,大概是NextToken的简化版,将一些逻辑写出来,嗯,用splitter作个最简单的示例。

 1 type
 2   TStr = record
 3     ptr: PChar;
 4     len: Integer;
 5   end;
 6
 7 // 将src的数据,进行分隔,分隔出来的数据放到s中
 8 // 成功,表示分隔成功,失败表示结束
 9 function splitter(var src, s: TStr): Boolean;
10 var
11   start: PChar;
12 begin
13   result := false;
14   if src.len <= 0 then exit;
15
16   // 1:保存原地址
17   start := src.ptr;
18   // 2: 移动到分隔字符处
19   while (src.len > 0) and not (src.ptr^ in [‘,‘, ‘;‘]) do
20   begin
21     inc(src.ptr);
22     dec(src.len);
23   end;
24   // 3: 检查分隔是否成功
25   result := src.ptr - start > 0;
26   if result then
27   begin
28     // 4: 成功,进行s赋值
29     s.ptr := start;
30     s.len := src.ptr - start;
31     // 5: 跳过分隔字符,等待下一次分隔
32     while (src.len > 0) and (src.ptr^ in [‘,‘, ‘;‘]) do
33     begin
34       inc(src.ptr);
35       dec(src.len);
36     end;
37   end;
38 end;
39
40 function splitter_string(var src: TStr; var s: string): Boolean;
41 var
42   sub: TStr;
43 begin
44   result := splitter(src, sub);
45   if result then
46     SetString(s, sub.ptr, sub.len);
47 end;
48
49 procedure TForm1.Button1Click(Sender: TObject);
50 var
51   src: TStr;
52   data, s: string;
53 begin
54   data := ‘a,b,c‘;
55   src.ptr := PChar(data);
56   src.len := Length(data);
57
58   while splitter_string(src, s) do
59     Memo1.Lines.Add(‘splitter: ‘ + s);
60 end;

原谅俺,一直不知道这种解析的方法叫啥名字(有知道的请告诉一下),或者就是个字符解析的逻辑而已?不过感觉不像。
    也许会有人问,为啥这么折腾,简单的分隔,用TString再加个属性设置,就可以得到结果了。

以上,只是一个示例,只是大概逻辑。也并非想进行分隔,而且在某些场合,是尽量少用字符串使用的,然后,这种法子就用处了。

这种方法应用场合,在字符串处理中进行:语法解析,真是无往不利,比如:表达式,XML,JSON,HTTP。。。

这种处理方法:PChar从头到尾扫描一次,然后就结束,中间穿插取数据的处理。所以速度非快。

且中间,如果需要可以不产生任何与内存分配/释放的处理(string操作需要GetMem+FreeMem),只记录地址+长度。

上例只是一简单的处理,还有是利用case,进行匹配各个字符,如XML中的字符"<", "/", ">",然后进行数据处理。

这部分内容,估计对解析有兴趣的才会看了,所以不再细写了。:D

总结:

有些东西很细化,总得说来PChar操作多种多样,因为指针本身就是自由度比较高的东西,再加上一些方法,组合起来就不用说了。

所以,也没法说的太清,感觉说来说去像是在绕圈子,还是说那些东西,所以,先写到这里吧。:)

水平有限,如有雷同,就是盗版!

2014.10.21 by qsl

时间: 2024-12-14 18:17:11

delphi.指针.PChar的相关文章

DELPHI指针的使用

DELPHI指针的使用 大家都认为,C语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上.因此,说指针是C语言的灵魂,一点都不为过.同时,这种说法也让很多人产生误解,似乎只有C语言的指针才能算指针.Basic不支持指针,在此不论.其实,Pascal语言本身也是支持指针的.从最初的Pascal发展至今的Object Pascal,可以说在指针运用上,丝毫不会逊色于C语言的指针. 以下内容分为八部分,分别是 一.类型指针的定义 二.无类型指针的定义 三.指针的解除引用 四.取地址(指针赋

delphi指针简单入门

delphi指针简单入门:         看一个指针用法的例子:     1         var     2             X,   Y:   Integer;       //   X   and   Y   整数类型     3             P:   ^Integer;           //   P   指向整数类型的指针     4         begin     5             X   :=17; //   给   X   赋值     6

Delphi 指针大全(光看不练是学不会的)

大家都认为,C语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上.因此,说指针是C语言的灵魂,一点都不为过.同时,这种说法也让很多人产生误解,似乎只有C语言的指针才能算指针.Basic不支持指针,在此不论.其实,Pascal语言本身也是支持指针的.从最初的Pascal发展至今的Object Pascal,可以说在指针运用上,丝毫不会逊色于C语言的指针. 以下内容分为八部分,分别是    一.类型指针的定义    二.无类型指针的定义    三.指针的解除引用    四.取地址(指针赋

Delphi 指针大全

- 1 -目 录1 DELPHI 的指针-引用.................................................................................- 1 -2 delphi 的"引用/值"模型..............................................................................- 5 -3 谈谈 Delphi 的类型与指针.................

delphi string,pchar,char的比较

来自:http://blog.163.com/kat_/blog/static/189284269201152513331999/ ------------------------------------------------------------------------------------- tring和Char数组都是一块内存, 其中存放连续的字符. string保存具体字符的内存对用户 是透明的, 由Delphi管理它的分配, 复制和释放, 用户不能干预(其实也可以, 不过是通过

delphi 指针 认识

delphi 指针分为类型指针和无类型指针: 类型指针分为PChar.PInteger.PString等. 无类型指针Pointer. PPChar/PP...为指针的指针 @和Addr一样,为获取变量存放的地址.^为指针指向的内容. @变量, Addr(变量), 指针^ var p: pChar; // 这样定义 p为类型指针:PChar() PInteger() PString()... PChar 可看做 ^Char begin p := 'China'; inc(p); p := p +

Delphi指针详解

Delphi指针详解2007-12-04 06:08:57|  分类: DLL学习 阅读91 评论0   字号:大中小 订阅 大家都认为,C语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上.因此,说指针是C语言的灵魂,一点都不为过.同时,这种说法也让很多人产生误解,似乎只有C语言的指针才能算指针.Basic不支持指针,在此不论.其实,Pascal语言本身也是支持指针的.从最初的Pascal发展至今的Object Pascal,可以说在指针运用上,丝毫不会逊色于C语言的指针. 以下内

Delphi指针运用理解

现在是面向对象漫天飞的年代了,大家都在在谈面向对象编程.Java对指针“避而不谈”,C#虽然支持指针运用,但是也淡化处理. 然而,指针还是好完全掌握为妙,省得在开发过程碰钉子,至于对指针的运用在于开发人员的存乎于心,运用得当.指针运用的不好,不要怪开发语言及其机制.下面谈到的是在Delphi中指针的运用,至于其他语言,指针的思想是相通的. 指针是一种数据类型,和编程语言中其它的类型一样,是一种类型的区分,比如 Integer 是带符号的整型,在32位X86机中,是用4个字节表示,而指针也是用4个

delphi指针

以下内容分为八部分,分别是 一.类型指针的定义 二.无类型指针的定义 三.指针的解除引用 四.取地址(指针赋值) 五.指针运算 六.动态内存分配 七.字符数组的运算 八.函数指针 一.类型指针的定义. 对于指向特定类型的指针,在C中是这样定义的: [cpp] view plain int *ptr; char *ptr; 与之等价的Object Pascal是如何定义的呢? [delphi] view plain var ptr : ^Integer; ptr : ^char; 其实也就是符号的