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

注意:

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

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

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

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

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

 用法一:

 var
p: PChar;
s: string;
begin
s := 'abc';
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进行缓存处理

 type
PMyString = ^TMyString;
TMyString = record
buf: PAnsiChar;
len: Integer;
buf_len: Integer;
end; // 初始化+分配空间
procedure string_init(var s: TMyString; buf_len: Integer);
begin
FillChar(s, SizeOf(s), );
s.buf := AllocMem(buf_len);
s.buf_len := buf_len;
end; // 反初始化+释放空间
procedure string_uninit(var s: TMyString);
begin
if s.buf_len > then
FreeMem(s.buf);
FillChar(s, sizeof(s), );
end; // 写数据(任意数据)
procedure string_write(var s: TMyString; buf: Pointer; len: Integer); overload;
begin
if len + s.len > s.buf_len then
begin
Inc(s.buf_len, len * );
ReallocMem(s.buf, s.buf_len);
end;
if len > then
begin
Move(buf^, (s.buf + s.len)^, len);
Inc(s.len, len);
end;
end; // 写数据(字符串数据)
procedure string_write(var s: TMyString; const AData: string); overload;
begin
string_write(s, PAnsiChar(AData), Length(AData) * sizeof(Char));
end; // 读数据(只针对字符串),读完后清除数据
function string_read(var s: TMyString): string;
begin
if s.len > then
begin
SetString(Result, s.buf, s.len);
s.len := ;
end else
Result := '';
end;

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

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

 result := PByte(s.buf)^;
result := PInteger(s.buf + )^;
result := PCardinal(s.buf + + )^;
result := PDouble(s.buf + + + )^;
result := PMsg(s.buf + + + + )^.wParam;

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

用法三:

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

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

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

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

 type
TStr = record
ptr: PChar;
len: Integer;
end; // 将src的数据,进行分隔,分隔出来的数据放到s中
// 成功,表示分隔成功,失败表示结束
function splitter(var src, s: TStr): Boolean;
var
start: PChar;
begin
result := false;
if src.len <= then exit; // :保存原地址
start := src.ptr;
// : 移动到分隔字符处
while (src.len > ) and not (src.ptr^ in [',', ';']) do
begin
inc(src.ptr);
dec(src.len);
end;
// : 检查分隔是否成功
result := src.ptr - start > ;
if result then
begin
// : 成功,进行s赋值
s.ptr := start;
s.len := src.ptr - start;
// : 跳过分隔字符,等待下一次分隔
while (src.len > ) and (src.ptr^ in [',', ';']) do
begin
inc(src.ptr);
dec(src.len);
end;
end;
end; function splitter_string(var src: TStr; var s: string): Boolean;
var
sub: TStr;
begin
result := splitter(src, sub);
if result then
SetString(s, sub.ptr, sub.len);
end; procedure TForm1.Button1Click(Sender: TObject);
var
src: TStr;
data, s: string;
begin
data := 'a,b,c';
src.ptr := PChar(data);
src.len := Length(data); while splitter_string(src, s) do
Memo1.Lines.Add('splitter: ' + s);
end;

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

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

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

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

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

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

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

注意点:

  1:p: PChar; p^ = 'a',如果不小心"^"未写,变成: p = 'a',编绎不出错,但结果不正确,少一个^符号非常难查找。

总结:

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

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

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

2014.10.21 by qsl

delphi.指针.PChar的更多相关文章

  1. Delphi的字符(Char),字符串(String),字符串指针(PChar),字符数组arrayofchar(来自http://delphi.cjcsoft.net/论坛)

    Delphi有三种类型的字符: AnsiChar这是标准的1字节的ANSI字符,程序员都对它比较熟悉. WideChar这是2字节的Unicode字符. Char在目前相当于AnsiChar,但在De ...

  2. Delphi指针的用法

    DELPHI指针的使用 大家都认为,C语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上.因此,说指针是C语言的灵魂,一点都不为过.同时,这种说法也让很多人产生误解,似乎只有C语言的指针才 ...

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

    大家都认为,C语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上.因此,说指针是C语言的灵魂,一点都不为过.同时,这种说法也让很多人产生误解,似乎只有C语言的指针才能算指针.Basic不支 ...

  4. delphi指针简单入门

    delphi指针简单入门:         看一个指针用法的例子:     1         var     2             X,   Y:   Integer;       //   ...

  5. delphi 指针 认识

    delphi 指针分为类型指针和无类型指针: 类型指针分为PChar.PInteger.PString等. 无类型指针Pointer. PPChar/PP...为指针的指针 @和Addr一样,为获取变 ...

  6. delphi string,pchar,char的比较

    来自:http://blog.163.com/kat_/blog/static/189284269201152513331999/ ---------------------------------- ...

  7. Delphi指针详解

    Delphi指针详解2007-12-04 06:08:57|  分类: DLL学习 阅读91 评论0   字号:大中小 订阅 大家都认为,C语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用 ...

  8. DELPHI指针的使用

    DELPHI指针的使用 大家都认为,C语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上.因此,说指针是C语言的灵魂,一点都不为过.同时,这种说法也让很多人产生误解,似乎只有C语言的指针才 ...

  9. delphi.指针.应用

    注:初稿...有点乱,可能增删改... 因为指针应用,感觉不好写,请大家指出错误,谢谢. 注意: 本文着重点讲的是指针的各类型的应用或使用,而不是说这种方法不应该+不安全+危险+不提倡使用. 其它:本 ...

随机推荐

  1. web安全之sql注入布尔注入

    条件: 当一个页面,存在注入,没显示位,没有数据库出错信息,只能通过页面返回正常不正常进行判断进行sql注入. 了解的函数 exists()                    用于检查  子查询是 ...

  2. js判断类型方法

    在JavaScript中,有5种基本数据类型和1种复杂数据类型,基本数据类型有:Undefined, Null,Boolean, Number和String:复杂数据类型是Object,Object中 ...

  3. 【转】对MVC、MVP、MVVM的懂得

    [转]对MVC.MVP.MVVM的懂得 转载地址:http://www.myexception.cn/vc-mfc/1612241.html 对MVC.MVP.MVVM的理解 最近看了一堆js框架的文 ...

  4. Java操作redis简单示例

    第一:安装Redis    首先我们要安装Redis,就像我们操作数据库一样,在操作之前肯定要先创建好数据库的环境.    Redis的下载可以百度一下,或者打开下面的下载链接:    https:/ ...

  5. 替换节点及replaceEach方法

    需求: 为所有的 li 节点添加 onclick 响应函数实现 city 子节点和 game 子节点对应位置的元素的互换 window.onload = function(){ //自定义互换两个节点 ...

  6. 用shebang编写一个ssh自动登陆脚本

    单例模式是软件开发中非常普遍的一种模式.它的主要作用是确保系统中,始终只存在一个类的实例对象. 这样做的好处有两点: 1.对于需要频繁使用的对象,在每次使用时,如果都需要重新创建,并且这些对象的内容都 ...

  7. 自学 PHP,如何不走弯路?

    1.一本好书至关重要.如果这本书的知识非常深入,那么还是不要看了.对初学者来说只能是打击.因为很多东西都看不懂.一本知识较为浅显,并且说明非常详细,但是能让你上手的基础知识又非常完善的书籍就非常好.( ...

  8. MySql 的常用优化

    1.选取最适用的字段属性 MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快.因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得尽 ...

  9. 王爽< 汇编语言>实验十二

    ;此乃安装程序 ;功能:将8086cpu中断类型码为0 的中断向量设置为我们编写的中断服务程序入口地址 ;该中断在除法发送溢出的时候产生 assume cs:code code segment mai ...

  10. glusterfs 中的字典查询

    glusterfs文件系统是一个分布式的文件系统,但是与很多分布式文件系统不一样,它没有元数服务器,听说swift上也是应用了这个技术的.glusterfs中每个xlator的配置信息都是用dict进 ...