字符提取的问题 (不要把它看得太容易了)(50分)

  • 主题发起人 主题发起人 Ourland
  • 开始时间 开始时间
O

Ourland

Unregistered / Unconfirmed
GUEST, unregistred user!
编程中偶尔有对源码操作的动作,有以下需求无法实现,请同志们伸出援手:
如何提取以指定的字符串开始、结束的字符串(要注意注释及嵌套),如提取
以begin开始、以end;结束的字符串(注意:有多层嵌套)。谢谢!(只要能
解决,分数可以商量)
 
你到底想做什么呀?没听太明白。:(
 
比如说有如下的代码:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
I:Integer;
begin
for I:=0 to 1000 do
begin
Form1.Caption:=Inttostr(I);
end;
end;

end.
我要提取Button1的事件代码、uses单元等等!
 
用堆栈就可以实现阿
比对begin的pos位置和end的pos位置,如果begin<end,压堆栈
begin>end 退堆栈,最后一个位置就是你需要的阿
 
sharman:不好意思,我水平太低,能不能给点源码,迫切需要,谢谢谢谢!!!
 
可以参阅源代码: DBCommon.pas中
function GetIndexForOrderBy(const SQL: string
DataSet: TDataSet): TIndexDef;
function GetTableNameFromSQL(const SQL: string): string;
使用的方法
 
设置一个变量,遇到begin就+1,遇到end就-1
 
编译原理的问题
 
同志们:你们说的我都没办法实现啊,能不能帮我写一段代码,最简单的也好哇,
实在没办法,急需要啊,谢谢谢谢!
 
不是吧,不难的呀,就是复杂一点。
不过真要做起来,是相当庞大的,因为有很多方面需要考虑:(
既然你要最简单的代码,那我给你写一个最简单的,提取引用单元,注意,
由于只是一个最简单的例子,没有考虑注释:

procedure GetUses(Code: string
Res: TStringList);
var
p: Integer;
begin
Res.Clear;

p := Pos('uses', Code);
Delete(Code, 1, p - 1 + 4{Length('uses')} + 2{Length(#13#10)})
// 删除 uses 以前的内容
p := Pos(';', Code);
Delete(Code, p, MaxInt)
// 删除 uses 以后的内容
Code := Trim(Code);

// 这个函数需要 uses Classes
ExtractStrings([','], [#13, #10, ' '], PChar(Code), Res);
end;

测试通过:
procedure TForm1.Button1Click(Sender: TObject);
var
s: TStringList;
begin
s := TStringList.Create;
s.LoadFromFile('D:/Program Files/Borland/Delphi6/Projects/unit1.pas');
GetUses(s.Text, s);
ShowMessage(s.Text);
s.Free;
end;
 
beta:你给的代码提取 Uses 确实可行,但问题的关键是出在注释和嵌套这个方面,
能不能在这方面再考虑一下,万分感谢!!!

问题还未解决,讨论中……
 
问题我已在我的论坛上回答,详情请看:
http://www.lvyin.net/bbs/dispbbs.asp?boardid=23&amp;rootid=64&amp;id=64&amp;star=

--------------------------------------
绿荫网络(http://www.lvyin.net)
 
要处理注释,最好还是逐字符分析,可以借鉴一下 SynEdit 的语法分析部分
不过逐字分析不适合你的提取部分,可以先扫描一遍,剔除所有注释,然后
再进行提取处理。
处理嵌套就麻烦了,基本方法正如楼上富翁所说,遇到一个 begin 加 1,遇到
一个 end 减 1. 不过要考虑 case 没有 begin 却对应一个 end,也就是说
遇到一个 case 也需要加 1. 麻烦吧:)实现起来还有更多东西需要考虑:(
 
你最好多给几个输入、输出范例
如果你都不知道起点和目的是什么
我想也没有会知道过程怎么做

嘻嘻嘻伴水[:)]到此一游嘻嘻嘻嘻
 
用正则表达式即可,我最近正在用他转换ubb代码
 
山泉:何谓“正则表达式”?来段源码如何(lizaiying12@163.com)
 
正则表达式是数据结构的只是,找本数据结构的书看看就知道了
不过你的这个应用不是正则表达式能够解决的:)我已经说过了
 
我刚用正则表达式写个提取了 并替换了网页的关于email 的所有的ubb代码,并转化为html代码
目前我正做一项目,目前几乎可以提取所有ubb代码--》html了
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,RegExpr,HyperLinksDecorator;

type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Memo2: TMemo;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);

private
{ Private declarations }
r : TRegExpr;
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

uses FReplace;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);

var
PrevPos : integer;
Result,AText,MailTemplate:string;
begin

//memo1.Clear;
AText:='';
Result:=Memo1.Text;
AText:=Result;
PrevPos := 1;
with TRegExpr.Create do
try
//-------------------------------------------------------------------------------
PrevPos := 1;
AText:=Result;
Result:='';
MailTemplate:='(/*)/])(.[^/[]*)(/[//EMAIL/])'
//过滤email
Expression := MailTemplate;
if Exec (AText) then
REPEAT
Result := Result + System.Copy (AText, PrevPos,
MatchPos [0] - PrevPos) + '<img align=absmiddle src=pic/email1.gif>'
+'<A HREF="mailto:'+match[2]+'" TARGET=_blank>'+match[3]+'</A>';
PrevPos := MatchPos [0] + MatchLen [0];
UNTIL not ExecNext;
Result := Result + System.Copy (AText, PrevPos, MaxInt)
// Tail
finally Free;
end;



memo2.text:=Result;
end;

procedure TForm1.FormCreate(Sender: TObject);
var r:TRegExpr;

begin
r := TRegExpr.Create;



end;



end.
 
我也遇到了这一问题。期待高人出现!
 
定位begin和end没有什么好说的了,就是使用pos函数。
要解决begin和end的嵌套问题,可以用这种方法。
赋初始值 iCount := 0;
从第一个begin开始 设置 Inc(iCount) 每找到一个end 就Dec(iCount)
如果iCount = 0 那么是找到了对应第一个begin 的end 了。
 
后退
顶部