本文最早在编程论坛上发表,文章地址:http://programbbs.com/bbs/view12-21351-1.htm,相关文件可以在上述地址的页面中下载。转载时请注明出处。
一、前言
通配符就是指“*”和“?”两个字符,“*”表示当前位置可以没有或者有多个任意字符;“?”表示当前位置有一个任意字符。通配符匹配在网上资料中都有讲到,但主要说的都是字符串匹配而不是文本查找。我结合通配符匹配的算法写了一个支持通配符的文本查找函数。这个函数的源代码可以在本楼末尾的压缩包中得到。现在先说一下通配符匹配的算法。
二、通配符匹配算法
利用包含通配符的模式串(以下简称模式串)进行文本查找,通常会匹配到一个不定长度的文本。所以匹配完成后不但要得到匹配文本的结束位置也要得到匹配文本的开始位置。现在先来看一个简单的问题:假设有长度为PLen的模式串P,以及长度为TLen的文本T。如果P中不包含通配符,那么用下面这个简单算法就可以完成查找:
function FindText1(P,T : PAnsiChar; PLen,TLen : Integer; var SelStart,SelEnd : Integer): Boolean;
var
PCur,TCur : Integer;
begin
result:=fa ......
方法1:可写为函数,再调用
Application.CreateForm(TForm1, Form1);
Form1.ShowModal;
Form1.Free;
方法2:
Form1:= TForm1.Create(Application);
try
Form1.ShowModal;
finally
FreeAndNil(Form1);
end;
方法3:
Form1:=TForm1.Create(self);
Form1.ShowModal;
Form1.Free;
Form1:=nil; ......
例如以下代码:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs;
type
TForm1 = class(TForm)
procedure one();
function two(x,y:integer):integer;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.one();
var
p : pointer;
begin
p:=@two;
end;
function TForm1.two(x,y:integer):integer;
begin
Result:=x+y;
end;
end.
在Delphi5中,没有任何问题,到了delphi7、2007、2009中就会报错:需要变量(Delphi6没试)
原因是新版本中要求返回函数地址的函数必须是全局函数,所以程序要改成这样:
................................
var
Form1: TForm1;
function two(x,y:integer):integer;
................................
function two(x,y:integer):integer; ......
实际上这个名字叫[SDL & Delphi]也不成问题, 因为除了Delphi似乎也没有哪个流行的开发工具用的是Pascal语言。
SDL其实我也只学了不到两星期而已。刚开始我想试图用VC,因为这样资料最全,也很好找,但太久没用VC现在看C的代码有点困难(->这个算符是干吗的来着……)。其实作为一个专业不是计算机的人,平时写一些程序都是用Delphi,这样我不必在界面上费劲,至于VC虽然用过但扔了很久了。后来我发现SDL有Object Pascal版本,就安装了一个,觉得用起来还是很方便的。
当然我说过我只是个业余的,所以我使用的一些代码可能不太正规,至少变量的匈牙利命名方法我是很少用的,只是我嫌打字费劲。还有我用的一些实现方法也许有更高效的方案。但我还是想把一些使用上的经验和走过的一些弯路写在这里,大家参考也好,找找毛病也好,我都是欢迎的。 ......
一些基础的问题我不再赘述了,查阅帮助文档(Object Pascal SDL Doc.chm)显然比在这看我胡扯合适得多。那些画像素,获取像素信息,显示BMP文件多数时候只要把那些代码复制过来基本就能工作。下面说的是怎样显示中文。
其实SDL加上ttf支持时(需要将对应的dll文件添加到工程目录里)是完全可以显示中文的,简体和繁体都没问题(Object Pascal版本也不缺功能),但是只能用Unicode编码。这就是说,你必须选择一个Unicode编码完整的字体文件(或者说至少你需要的那些字符是完整的)。Windows下面这样的字体有很多,我推荐的有:
简体中文:宋体大字符集,微软雅黑;
繁体中文:细明体,微软正黑,标楷体。
这些基本是中文地区最重要的几种字体。一个缺憾就是用于显示简体中文的楷体(和其他字体)优秀的并不多。
输出中文时,可以先写这样的一个子程作为基础:
procedure DrawText(word: PUint16; x_pos, y_pos: integer; color: Uint32);
var
text: PSDL_Surface;
dest: TSDL_Rect;
begin
text := TTF_RenderUNICODE_blended(font, word, TSDL_Color(Color));
dest.x := x_pos;
dest.y := y_pos;
......
一个选单大致是这样:
1.可以被以某种形式呼叫出来,如按下esc;
2.在这个选单中功能键有不同的定义,如原本方向键控制走路,但现在改为控制光标的位置;
3.按下确定键后有对应功能被执行;
4.可以被关闭。
那么我的办法是编写两个子程,其中一个处理选单中的事件,另外一个专门负责画选单。
在从步行切换到选单的时候,可能需要清除当前的键值。如果步行中使用了SDL_EnableKeyRepeat方法把键盘的频率变高,对于选单来说就太快了。所以可能要在调用选单之前写上:
SDL_EnableKeyRepeat(0, 0);
event.key.keysym.sym := 0;
这样降低了键盘的反应,同时清除当前的键值,要不然呼出选单之后它可能还会自己转一会(如果之前用了PollEvent方式,我还没搞清楚原因)。不过如果在行走中使用的是WaitEvent方式,事情就会简单很多。PollEvent方式看来是太快了,在选单中不合适。
处理选单事件的子程:
procedure MenuSystem;
var
menu: integer;
begin
while (SDL_WaitEvent(@event) >= 0) do
begin
case event.type_ of
SDL_QUITEV: //这里处理窗口退出事件
  ......