本文转贴自opera的一篇blog上(貌似现在很多人搬去哪里),很久没有看这样的类技术性文章了,花半个小时快速浏览了下,长了见识~转贴此文并不代表本blog同意其观点,转贴而已,希望不会因为内容敏感而被禁发(曾经在网易有过这样的经历,可以告诉您,本文网上copy的n多,不过这个是完整的10篇,希望不要因为仅仅出现类似政府,警察的字样就不让发,否则我也要搬家了)
Aug 30, 2008
转帖:黑客眼里的隐私
本文转贴自opera的一篇blog上(貌似现在很多人搬去哪里),很久没有看这样的类技术性文章了,花半个小时快速浏览了下,长了见识~转贴此文并不代表本blog同意其观点,转贴而已,希望不会因为内容敏感而被禁发(曾经在网易有过这样的经历,可以告诉您,本文网上copy的n多,不过这个是完整的10篇,希望不要因为仅仅出现类似政府,警察的字样就不让发,否则我也要搬家了)
Aug 23, 2008
(回味)指针的应用
CYouSDIDoc *pDoc=GetDocument();一个视只能有一个文档。2) 在App中获得MainFrame指针
CWinApp 中的 m_pMainWnd变量就是MainFrame的指针
也可以:
CMainFrame *pMain =(CMainFrame *)AfxGetMainWnd();3) 在View中获得MainFrame指针
CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd;4) 获得View(已建立)指针
CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd; CyouView *pView=(CyouView *)pMain->GetActiveView();5) 获得当前文档指针
CDocument * pCurrentDoc =(CFrameWnd *)m_pMainWnd->GetActiveDocument();6) 获得状态栏与工具栏指针
CStatusBar * pStatusBar=(CStatusBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR); CToolBar * pToolBar=(CtoolBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);7) 如果框架中加入工具栏和状态栏变量还可以这样
(CMainFrame *)GetParent()->m_wndToolBar; (CMainFrame *)GetParent()->m_wndStatusBar;8) 在Mainframe获得菜单指针
CMenu *pMenu=m_pMainWnd->GetMenu();9) 在任何类中获得应用程序类
用MFC全局函数AfxGetApp()获得。
Aug 20, 2008
VS IDE
重构菜单:重构是编写代码后在不更改代码的外部行为的前提下,通过更改代码的内部结构来改进代码的过程。这段话的意思是写完代码后还可以修改它以增强代码的可读性和可维护性。重构菜单项在查看代码窗口中的网页,用户控件,语言代码时可用,也可以通过右键单击类视图,对象浏览器和解决方案资源管理器中的标识符,在弹出的上下文菜单中使用重构。
重构菜单包括一下功能:重命名,提取方法,封装字段,提取接口,将局部变量提升为参数,移除参数,重新排列参数。
封装字段:利用现有的公共字段创建属性,并更新代码使之引用新属性来代替引用字段。之前的公共字段转换为私有的,创建get 和set访问器,一次控制外部对该字段的访问。如果原始字段被声明为read_only则不会创建set服务器
提取接口:如果多个类,结构或者接口使用一组公共成员,则吧这些公共成员提取到一个接口中会更好一些,该接口可以由原始类,结构或接口实现
Aug 16, 2008
动态网站
Aug 14, 2008
【典藏】列函数与散列表(哈希函数、哈希表、Hash函数、Hash表)
散列方法不同于顺序查找、二分查找、二叉排序树及B-树上的查找。它不以关键字的比较为基本操作,采用直接寻址技术。在理想情况下,无须任何比较就可以找到待查关键字,查找的期望时间为O(1)。
一、散列表的概念
1、散列表
设所有可能出现的关键字集合记为U(简称全集)。实际发生(即实际存储)的关键字集合记为K(|K|比|U|小得多)。
散列方法是使用函数h将U映射到表T[0..m-1]的下标上(m=O(|U|))。这样以U中关键字为自变量,以h为函数的运算结果就是相应结点的存储地址。从而达到在O(1)时间内就可完成查找。其中:
① h:U→{0,1,2,…,m-1} ,通常称h为散列函数(Hash Function)。散列函数h的作用是压缩待处理的下标范围,使待处理的|U|个值减少到m个值,从而降低空间开销。
② T为散列表(Hash Table)。
③ h(K i )(K i ∈U)是关键字为K i 结点存储地址(亦称散列值或散列地址)。
④ 将结点按其关键字的散列地址存储到散列表中的过程称为散列(Hashing)
2、散列表的冲突现象
(1)冲突
两个不同的关键字,由于散列函数值相同,因而被映射到同一表位置上。该现象称为冲突(Collision)或碰撞。发生冲突的两个关键字称为该散列函数的同义词(Synonym)。
【例】上图中的k 2 ≠k 5 ,但h(k 2 )=h(k 5 ),故k 2 和K 5 所在的结点的存储地址相同。
(2)安全避免冲突的条件
最理想的解决冲突的方法是安全避免冲突。要做到这一点必须满足两个条件:
①其一是|U|≤m
②其二是选择合适的散列函数。这只适用于|U|较小,且关键字均事先已知的情况,此时经过精心设计散列函数h有可能完全避免冲突。
(3)冲突不可能完全避免
通常情况下,h是一个压缩映像。虽然|K|≤m,但|U|>m,故无论怎样设计h,也不可能完全避免冲突。因此,只能在设计h时尽可能使冲突最少。同时还需要确定解决冲突的方法,使发生冲突的同义词能够存储到表中。
(4)影响冲突的因素
冲突的频繁程度除了与h相关外,还与表的填满程度相关。设m和n分别表示表长和表中填人的结点数,则将α=n/m定义为散列表的装填因子(Load Factor)。α越大,表越满,冲突的机会也越大。通常取α≤1。
二、散列函数的构造方法
1、散列函数的选择有两条标准:简单和均匀。
简单指散列函数的计算简单快速;均匀指对于关键字集合中的任一关键字,散列函数能以等概率将其映射到表空间的任何一个位置上。也就是说,散列函数能将子集K随机均匀地分布在表的地址集{0,1,…,m-1}上,以使冲突最小化。
2、常用散列函数
为简单起见,假定关键字是定义在自然数集合上。其它关键字可以转换到自然数集合上。
(1)平方取中法
具体方法:先通过求关键字的平方值扩大相近数的差别,然后根据表长度取中间的几位数作为散列函数值。又因为一个乘积的中间几位数和乘数的每一位都相关,所以由此产生的散列地址较为均匀。
【例】将一组关键字(0100,0110,1010,1001,0111)平方后得 (0010000,0012100,1020100,1002001,0012321) ,若取表长为1000,则可取中间的三位数作为散列地址集:(100,121,201,020,123)。相应的散列函数用C实现很简单:
int Hash(int key){ //假设key是4位整数
key*=key; key/=100; //先求平方值,后去掉末尾的两位数
return key%1000; //取中间三位数作为散列地址返回
}
(2)除余法
该方法是最为简单常用的一种方法。它是以表长m来除关键字,取其余数作为散列地址,即 h(key)=key%m。该方法的关键是选取m。选取的m应使得散列函数值尽可能与关键字的各位相关。m最好为素数。
【例】若选m是关键字的基数的幂次,则就等于是选择关键字的最后若干位数字作为地址,而与高位无关。于是高位不同而低位相同的关键字均互为同义词。
【例】若关键字是十进制整数,其基为10,则当m=100时,159,259,359,…,等均互为同义词。
(3)相乘取整法
该方法包括两个步骤:首先用关键字key乘上某个常数A(0
该函数的C代码为:
int Hash(int key){ double d=key *A; //不妨设A和m已有定义 return (int)(m*(d-(int)d));//(int)表示强制转换后面的表达式为整数 } (4)随机数法 选择一个随机函数,取关键字的随机函数值为它的散列地址,即h(key)=random(key)其中random为伪随机函数,但要保证函数值是在0到m-1之间。 (5)数字分析法 设有 n 个 d 位数,每一位可能有 r 种不同的符号。这 r 种不同的符号在各位上出现的频率不一定相同,可能在某些位上分布均匀些,每种符号出现的几率均等; 在某些位上分布不均匀,只有某几种符号经常出现。可根据散列表的大小,选取其中各种符号分布均匀的若干位作为散列地址。 (6)基数转换法 将关键码值看成另一种进制的数再转换成原来进制的数,然后选其中几位作为散列地址。 (7)折叠法 有时关键码所含的位数很多,采用平方取中法计算太复杂,则可将关键码分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为散列地址,这方法称为折叠法。 (8)ELFhash字符串散列函数 ELFhash函数在UNIX系统V 版本4中的“可执行链接格式”( Executable and Linking Format,即ELF )中会用到,ELF文件格式用于存储可执行文件与目标文件。ELFhash函数是对字符串的散列。它对于长字符串和短字符串都很有效,字符串中每个字符都有同样的作用,它巧妙地对字符的ASCII编码值进行计算,ELFhash函数对于能够比较均匀地把字符串分布在散列表中。
三、处理冲突的方法 通常有两类方法处理冲突:开放定址(Open Addressing)法和拉链(Chaining)法。前者是将所有结点均存放在散列表T[0..m-1]中;后者通常是将互为同义词的结点链成一个单链表,而将此链表的头指针放在散列表T[0..m-1]中。 1、开放定址法 (1)开放地址法解决冲突的方法 用开放定址法解决冲突的做法是:当冲突发生时,使用某种探查(亦称探测)技术在散列表中形成一个探查(测)序列。沿此序列逐个单元地查找,直到找到给定的关键字,或者碰到一个开放的地址(即该地址单元为空)为止(若要插入,在探查到开放的地址,则可将待插入的新结点存人该地址单元)。查找时探查到开放的地址则表明表中无待查的关键字,即查找失败。注意: ①用开放定址法建立散列表时,建表前须将表中所有单元(更严格地说,是指单元中存储的关键字)置空。 ②空单元的表示与具体的应用相关。 【例】关键字均为非负数时,可用"-1"来表示空单元,而关键字为字符串时,空单元应是空串。 总之:应该用一个不会出现的关键字来表示空单元。 (2)开放地址法的一般形式 开放定址法的一般形式为: h i =(h(key)+d i )%m 1≤i≤m-1.其中: ①h(key)为散列函数,d i 为增量序列,m为表长。 ②h(key)是初始的探查位置,后续的探查位置依次是h l ,h 2 ,…,h m-1 ,即h(key),h l ,h 2 ,…,h m-1 形成了一个探查序列。 ③若令开放地址一般形式的i从0开始,并令d 0 =0,则h 0 =h(key),则有: h i =(h(key)+d i )%m 0≤i≤m-1.探查序列可简记为h i (0≤i≤m-1)。 (3)开放地址法堆装填因子的要求 开放定址法要求散列表的装填因子α≤l,实用中取α为0.5到0.9之间的某个值为宜。 (4)形成探测序列的方法 按照形成探查序列的方法不同,可将开放定址法区分为线性探查法、二次探查法、双重散列法等。 ①线性探查法(Linear Probing) 该方法的基本思想是:将散列表T[0..m-1]看成是一个循环向量,若初始探查的地址为d(即h(key)=d),则最长的探查序列为:d,d+l,d+2,…,m-1,0,1,…,d-1 .即:探查时从地址d开始,首先探查T[d],然后依次探查T[d+1],…,直到T[m-1],此后又循环到T[0],T[1],…,直到探查到T[d-1]为止。探查过程终止于三种情况: (1)若当前探查的单元为空,则表示查找失败(若是插入则将key写入其中); (2)若当前探查的单元中含有key,则查找成功,但对于插入意味着失败; (3)若探查到T[d-1]时仍未发现空单元也未找到key,则无论是查找还是插入均意味着失败(此时表满)。 利用开放地址法的一般形式,线性探查法的探查序列为: h i =(h(key)+i)%m 0≤i≤m-1 //即d i =i 【例9.1】已知一组关键字为(26,36,41,38,44,15,68,12,06,51),用除余法构造散列函数,用线性探查法解决冲突构造这组关键字的散列表。
与开放定址法相比,拉链法有如下几个优点:(1)拉链法处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短;(2)由于拉链法中各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况;(3)开放定址法为减少冲突,要求装填因子α较小,故当结点规模较大时会浪费很多空间。而拉链法中可取α≥1,且结点较大时,拉链法中增加的指针域可忽略不计,因此节省空间;(4)在用拉链法构造的散列表中,删除结点的操作易于实现。只要简单地删去链表上相应的结点即可。而对开放地址法构造的散列表,删除结点不能简单地将被删结点的空间置为空,否则将截断在它之后填人散列表的同义词结点的查找路径。这是因为各种开放地址法中,空地址单元(即开放地址)都是查找失败的条件。因此在用开放地址法处理冲突的散列表上执行删除操作,只能在被删结点上做删除标记,而不能真正删除结点。 (3)拉链法的缺点 拉链法的缺点是:指针需要额外的空间,故当结点规模较小时,开放定址法较为节省空间,而若将节省的指针空间用来扩大散列表的规模,可使装填因子变小,这又减少了开放定址法中的冲突,从而提高平均查找速度。
四、散列表上的运算 散列表上的运算有查找、插入和删除。其中主要是查找,这是因为散列表的目的主要是用于快速查找,且插入和删除均要用到查找操作。 1、散列表类型说明: #define NIL -1 //空结点标记依赖于关键字类型,本节假定关键字均为非负整数 #define M 997 //表长度依赖于应用,但一般应根据。确定m为一素数 typedef struct{ //散列表结点类型 KeyType key; InfoType otherinfo; //此类依赖于应用 }NodeType; typedef NodeType HashTable[m]; //散列表类型 2、基于开放地址法的查找算法 散列表的查找过程和建表过程相似。假设给定的值为K,根据建表时设定的散列函数h,计算出散列地址h(K),若表中该地址单元为空,则查找失败;否则将该地址中的结点与给定值K比较。若相等则查找成功,否则按建表时设定的处理冲突的方法找下一个地址。如此反复下去,直到某个地址单元为空(查找失败)或者关键字比较相等(查找成功)为止。 (1)开放地址法一般形式的函数表示 int Hash(KeyType k,int i) { //求在散列表T[0..m-1]中第i次探查的散列地址hi,0≤i≤m-1 //下面的h是散列函数。Increment是求增量序列的函数,它依赖于解决冲突的方法 return(h(K)+Increment(i))%m; //Increment(i)相当于是d i } 若散列函数用除余法构造,并假设使用线性探查的开放定址法处理冲突,则上述函数中的h(K)和Increment(i)可定义为: int h(KeyType K){//用除余法求K的散列地址 return K%m; } int Increment(int i){ //用线性探查法求第i个增量d i return i; //若用二次探查法,则返回i*i } (2)通用的开放定址法的散列表查找算法: int HashSearch(HashTable T,KeyType K,int *pos) { //在散列表T[0..m-1]中查找K,成功时返回1。失败有两种情况:找到一个开放地址 //时返回0,表满未找到时返回-1。 *pos记录找到K或找到空结点时表中的位置 int i=0; //记录探查次数 do{ *pos=Hash(K,i); //求探查地址hi if(T[*pos].key==K) return l; //查找成功返回 if(T[*pos].key==NIL) return 0;//查找到空结点返回 }while(++i
Aug 13, 2008
Programming ASP.NET笔记:控件
第三章:控件:基本概念
控件是构建图形用户界面(GUI)的模块
Web控件包括四种类型:HTML控件;HTML服务器控件;ASP.NET服务器控件;用户控件和自定义控件。
ASP.NET服务器控件包括:文本,标签等;验证控件;数据源控件;数据视图控件;个性化控件;登陆控件和安全控件;母版页;富控件(rich controls)
事件:执行程序有两种模式(二者并不是非此即彼的关系)线性模式和事件驱动模式。
线性模式的程序从第一步开始执行,直到所有步骤执行完为止;代码中的流控制结构(循环,IF或者方法调用)或许可以重定位程序的留,然而就本质而言,一旦程序开始执行,在用户或系统的操作下,它将一直运行下去。在有GUI环境之前大多数计算机程序都是线性模式。
时间驱动模式是指发生某些事情时进行响应。多数情况下事件由用户行为生成,但是由系统出发。服务器控件是可以触发事件的对象,用户在浏览器上对服务器控件所执行的任何行为都可能触发事件。
事件参数:事件依靠委托实现。委托是一个对象,它封装了对方法的描述,即处理事件所制定的任务
按照管理,所有ASP.NET事件处理程序都有两个参数,并且返回空值。第一个参数表示触发事件的对象,习惯称为sender。尽管这不是必要的;第二个参数称作事件参数,它包括事件信息的细节。如果有的话,对于多数事件,事件参数是EventArgs类型,它没有任何属性。因此,事件的通用原型为private void EventName (object sender , EventArgs e)
对于某些控件,事件参数可以从EventArgs类派生,并显示该事件类型的属性细节。例如,AdRotator控件的AdCreated事件处理程序,接收AdCreatedEventArg类型的参数,它有AdProperties,AlternateText,ImageUrl和NavigateUrl属性。
应用程序事件和会话事件:当应用程序启动时,将触发Application_Start事件,这时,可以初始化整个应用程序中需要使用的各种资源。当应用程序停止时将触发Application_End事件,此时可以关闭资源,同时执行任何其他必要的日常管理。垃圾回收机制将自动释放内存。然而,如果分配了托管的资源,必须手工清楚
会话事件也是如此,当用户第一次请求应用程序页面时,会话开始。当应用程序关闭会话或会话超市,会话结束。当会话开始时触发Session_Start事件,可以初始化会话生命周期中使用的资源;会话结束时触发Session_End事件
页面和控件事件:页面和控件都包含事件,它们继承自control类(Error事件的情况下则继承自TemplateControl类)
部分公共的页面和控件事件:DataBinding;Disposed当控件从内存中释放时发生;Error只在页面中(当抛出为处理的异常时发生),Init当控件初始化时产生,Load当控件加载到页面对象时发生;PreRender当控件准备输出时发生;Unload当控件从内存中卸载时发生
回传事件vs非回传事件
回传事件促使表单立刻回传到服务器。某些事件(典型的有修改事件如TextBox。TextChanged或者选择事件CheckBox。CheckedChanged)被认为是非回传的,因为事件并不立刻回传到服务器。这些事件由控件捕获知道再次发生回传。设置非回传事件控件的AutoPostBack属性为TRUE可以强制回传。
回传控件:Button,Calendar,DataGrid,DataList,FileUpload,GridView,ImageButton,ImageMap,LinkButton,Menu,Repeater
非回传控件BulletedList,CheckBox,CheckBoxList,DropDownList,ListBox,RadioButtonList,RadioButton,TextBox
IsPostBack
Page对象具有IsPostBack属性。这是一个制度的Boolean类型属性。可以指示页面是第一次加载还是为了响应客户端回传而进行的加载。你可以只在页面第一次加载时执行一些耗费资源的操作;如果页面回传到服务器并再次加载,就无需重复这些操作了因为任何输入或构建的数据都议被保留到后续的回传中
Visual Studio 2005中的事件
当新建一个Web应用程序时,VS将自动包含下面的代码,以便处理页面加载事件
Protected void Page_Load(object sender,EventArgs e)
{
}
每个页面都包含多个类似Page_Load,可创建处理程序的事件,这些预定义事件处理程序的名称由Page_连接时间名组成,下边的事件处理程序会自动关联到他们相对应的事件
Page_load Page_AbortTransaction
Page_CommitTransaction Page_DataBinding
Page_Disposed Page_Error
Page_Init Page_InitComplete
Page_Load Page_LoadComplete
Page_PreInit Page_PreLoad
Page_PreRender Page_PreRenderComplete
Page_SaveStateComplete Page_Unload
控件有其默认事件。多个控件可以公用一个时间处理程序。例如,有一个普通的按钮单击时间处理程序它可以处理船体上所有按钮的单击时间,通过测试sender参数值,可以确定触发事件的具体按钮。下列代码,单击按钮的时间处理程序将sender对象转换为Button类型,然后将该按钮ID属性赋值给一个字符串变量
Private void BtnClick(object sender , System.EventArgs e)
{
Button b = sender as Button;
String buttonID= b.ID;
Switch (buttonID)
{
Case “btnDoThis”:
//
Case “btnDoThat”:
//
}
//所有按钮的通用代码
}
ASP.NET中最为重要的是ASP.NET服务器控件,包含方法以及与之相关的时间处理程序,并且这些代码都在服务器端执行(部分服务器控件也提供客户端脚本,尽管如此这些控件事件仍然会在服务器端处理)
如果控件包括可视化组成部分(按钮,表格等)ASP.NET将在家侧目标浏览器接收能力的情况下为浏览器呈现传统的HTML,如果需要利用客户端脚本,将会生成适应于浏览器类型的脚本并发送给浏览器。
因为发送给客户端的是最普通的HTML代码所以ASP.NET应用程序可以运行在任何浏览器上。所有的处理过程都在服务器段完成。同时ASP.NET服务器控件在浏览器中最终呈现为标准的HTML代码。另外,所发送的脚本并非是必须经过优化的。
Aug 9, 2008
fmod()值,终结
哎,问题的关键还是处在加法上面
我的失误啊,得补补C语言数据类型了
浮点型变量是由有限的存储单元组成的,因此能提供的有效数字总是有限的
有效位以外的数字将被舍去
一个浮点型变量保证的有效数字是7位
后几位是不准确的,对于加法来说就没有意义了
比如以下程序
/*--------------
浮点型数据的舍入误差
----------------*/
#include
void main()
{
float a,b;
a = 123456.789e5;
b = a + 20;
printf("%f\n",b);
}
程序输出a与b相等
因为a的值比20大很多。b理论值为12345678920
而一个浮点型变量只能保证的有效数字是7位,后面的数字无意义,不能准确表示
输出为12345678848.000000
前八位是准确的,后几位不准确,把20加上去是没有意义的
与此类似,用程序计算1.0/3.0*3结果不等于1
其实将float改成double就几乎不存在舍入的问题了。。。
fine。继续奋斗
关于fmod()函数问题的一点想法
一个奇怪的问题
Aug 7, 2008
编译原理基础
编译原理基础
编译程序是现代计算机系统的基本组成部分。从功能上看,一个编译程序就是一个语言翻译程序,把一种语言书写的程序(源程序)翻译成另一种语言(目标程序)的等价的程序
软件,计算机系统中的程序及其文档
系统软件,居于计算机系统中最靠近硬件的一层,如编译系统和操作系统等
语言处理系统,把软件语言书写的各种程序处理成可在计算机上执行的程序。
软件语言:用于书写软件的语言,主要包括需求定义语言,功能性语言,设计性语言,程序
设计语言以及文档语言
编译逻辑过程:
词法分析,语法分析,语义分析,中间代码生成,代码优化,目标代码生成
编译阶段的组合
分析,综合:源程序分析(线性分析,层次分析,语义分析),目标程序的综合
编译的前端(front end)
编译的后端(back end)
遍历一遍(pass):从头到尾扫描源程序
什么是词法分析程序:逐个读入源程序字符并按照构词规则分成一系列单词。单词是语言中具有独立意义的最小单位,包括保留字,标识符,运算符,标点符号和常量
词法分析是编译过程中的一个阶段,在语法分析前进行,页可以和语法分析结合在一起作为一遍。由语法分析程序调用词法分析程序来获得当前单词供语法分析使用
词法分析程序的主要任务:读源程序,产生单词符号
词法分析程序的其他任务:滤掉空格,跳过注释,换行符;追踪换行表示,复制出错源程序;宏展开
符号串的运算:
符号串的头,尾,固有头和固有尾:z=xy,x是z的头,y是z的尾。若x非空,那么y是固有尾;同样y非空的话x是固有头 z=abc,那z的头是a,ab,abc,除abc外都是固有透;z的尾是c,bc,abc,除abc外均是固有尾。当对符号串z = xy头感兴趣对其余部分不感兴趣,可以简写z = x…;如果只是强调x在符号串z中某处出现,可以表示为z=…x…;符号t是符号串z的第一个符号,则表示为z=t…
符号串的连接:假设x,y是符号串,他们的连接xy是吧y的符号卸载x的符号后面得到的符号串
符号串的方幂:
符号串集合:集合A中所有元素都是某字母表∑上的符号串,则A为字母表上的符号串集合
两个符号串集合A和B的乘积定义为AB={xy|x∈A且y∈B}
正规表达式与正规集
程序设计语言中的单词是基本语法成分,单词符号的语法可以用有效的工具加以描述,并且基于这类描述,实现词法分析程序的自动构造
一些基本术语和概念:
符号:一个抽象实体,字母和数字都是符号
字母表;是元素的非空有穷集合,不同的语言可以有不同的字母表
符号串;由字母表中的符号组成的任何有穷序列陈伟符号串
符号串的长度:符号串中有多少个符号就是多长
空符号串;不包含任何符号的符号串
正规式:也称正则表达式,是定义正规集的数学工具,我们用以描述单词符号。
状态转换图:是设计词法分析器的一种好途径。转换图是一张有限方向图,结点代表状态,用圆圈表示;状态之间用箭弧连接。箭弧上标记代表在射出结点状态下可能出现的输入字符或者字符类
确定的有穷自动机DFA:一个确定的有穷自动机M是一个五元组M=(K,f,S,Z)其中K是一个有穷集,它的每个元素称为一个状态,∑是一个有穷字母表,它的每一个元素称为一个输入符号;f是转换函数,是在k×∑->K的映射,S∈K是唯一的一个初态;Z包含于K是一个终态集,终态页可称为接受状态或结束状态
一个DFA可以表示成一个状态图(或称状态转换图),整个图有唯一一个初态结点和若干个终态结点。
不确定的有穷自动机NFA
例题:写出一定条件的文法和正则表达式
文法和语言概述:当我们表述一种语言时,无非是说明这种语言的句子,如果语言只含有有穷多个句子,则只需列出句子的有穷集就行了;但对于含有无穷句子的语言来讲,存在着如何给出它的有穷表示的问题。但是人们可以给出一些规则用来说明(或者定义)句子的组成结构
如果语言是无穷的,找出语言的有穷表示,语言的有穷表示有两个途径
生成方法(文法):语言中的每个句子可以用严格定义的规则来构造
识别方式(自动机):用一个过程,当输入的一任意串属于语言时,该过程经有限次计算后就会停止并回答“是“,若不属于,要么能停止并回答”不是“,要么永远继续下去
Aug 6, 2008
UML基础
Uml的基本概念:unified modeling language
通用可视化建模语言,能与所有的开发方法一起使用,可用于软件开发的整个生命周期
能表达系统的静态结构和动态信息,能管理复杂的系统模型
Uml不是编程语言:支持uml语言的工具可以提供从UML到各种编程语言的代码生成,提供从现有程序你想构建UML模型
Uml是一种离散的建模语言。
Uml的另一个目标是:能尽量简介的表达系统的模型
UML的概念范围:系统需求,静态结构,动态行为,交互行为,物理实现,各种图之间的关系,模型组织,扩展机制。
系统需求:用例视图:从外部用户的角度来秒素系统的行为,它将系统划分为对用于有意义的事务。
静态结构:静态视图,一个模型必须先定义各种事务的内部特征和相互之间的关系。
动态行为:状态机视图:对每个类的对象的生命周期进行建模,秒素对象时间上的动态行为。活动视图:利用状态机对运算和工作流进行建模的特殊形式
交互行为:交互视图:对象通过交互来实现行为,通过协作来进行建模。协作有结构和行为两方面
物理实现:物理视图。
各种图间的关系:静态视图(类图,对象图)物理视图(实现视图,部署视图)是描述系统的静态结构
用例图是描述系统的外部结构;活动图是描述系统的内、外部视图
交互视图(顺序图,协作图)描述系统的内部视图
状态图:描述单个类的动态行为
扩展机制:包括约束,标签值和原型。这些扩展机制可以用来为特定领域剪裁UML的配置。根据自身需要来使用建模语言。
静态建模:一个模型必须先定义各种事务的内部特征和相互间的联系。基本的模型元素:
分类:类,接口,子系统(Sub System),执行者,用例(Use cases),组件(Component)结点,注释(Comment)
关系:关联(Association),泛化(Generalization),依赖(dependecy),实现,约束(constraint)
静态视图:类图,对象图
类:具有相同属性,操作和关系的对象集合的总称。通常在UML中画成矩形,包括三个部分:名称:每个类必须有一个名字,属性:类可以有任意多个属性,也可以没有属性,操作:操作是类的任意一个实例对象都可以调用的,并可能影响对象行为的实现
接口:为给出实现对象行为的描述。接口包含操作,但没有属性。一个或多个类可以实现接口的操作
子系统:任何大的系统都必须划分为较小的单元。包可以包含各种模型元素和其他的包,包之间还可能存在一定的依赖。子系统是具有独立的说明和实现部分的包:代表了与系统其他部分具有清晰接口的清晰单元。通常代表了系统在功能或实现范围上的划分
执行者是与系统,子系统或类交互的外部人员,进程或事务。
用例是系统提供的外部可感知的功能单元。
组件:可重用的系统片段,具有良好定义接口的物理实现单元,每个组件包含系统设计中某些类的实现
组件设计的原则:良好的组件不直接依赖与其他组件而是依赖于其他组件所支持的接口,好处是系统中的组件可以被支持相同接口的组件所取代
一个组件可能是源代码,动态链接库或可执行程序
结点代表系统运行时的物理对象,通常拥有运算能力,它可以容纳对象和组件实例
注释用于解释设计的思路,便于理解
关联:描述了系统中对象和其他实例之间的离散的连接
聚集:用来表达整体-部分关系的关联
组合:是一种聚集,是关联更强的形式
泛化是一般化和具体化之间的关系
多重继承:可能存在冲突。最好显示解决冲突问题
依赖:指明两个或两个以上模型元素之间的关系
实现:是依赖的一种,但有特殊的意义。实现是连接说明和实体间的关系
约束:用来表述各种限制
静态视图表现为类图,主要描述类和类之间的关系,是UML的基础
对象图是系统在某一时刻的快照
动态建模:状态机图:对单个类的对象的生命周期进行建模。
用例图:描述各个执行者在各个用例中的参与情况,描述系统为用户所感知的外部视图。
用例图的功能:捕获系统用户需求,描述系统边界,指明系统外部行为,指导系统开发者的功能开发,系统建模的起点指导所有的类图和交互图的设计;产生测试用例,用户文档;估计项目大小和进度。
活动图:用状态机对工作流进行建模的特殊形式,支持并发控制
交互视图:对象行为是通过交互来实现的,交互是对象间为完成某一目的而进行的一系列消息交换
协作图:包含分类角色和关联角色。
物理架构:实现视图:描述可重用的系统组件及组件之间的依赖
部署视图:描述系统资源在运行时的物理分布,系统资源成为结点
UML是一种建模语言而不是方法,这是因为UML中没有过程的概念,而过程正是方法的一个重要组成部分。UML本身独立于过程,这一味这用户在使用UML进行建模时可以选用任何适合的过程
建模步骤:一般的建模过程有:瀑布式开发模型,迭代递增开发模型
基于UML的系统开发采取增量迭代开发的模型:
1 需求:最初需求规格说明应当由代表系统最终用户的人员提供,内容包括系统基本功能需求和对计算机系统的需求
2分析:分析的任务是找出系统的所有需求并加以描述,同时建立模型以定义系统中的关键领域类。应由系统用户和开发人员合作完成。
3设计:设计阶段任务是通过综合考虑所有的技术限制,以扩展和细化分析阶段的模型,分为结构设计和详细设计
结构设计:一个设计良好的系统结构是系统可扩充和可变更的基础。
详细设计:目的是通过创建新的类图,状态图和动态图,描述新的技术类,并扩展和细化分析阶段的对象类、
4实现:构造或实现阶段是对类进行编程的过程。
5测试和配置:完成系统编码后,需要对系统进行测试,包括单元测试,集成测试,系统测试和验收测试
Rose是Rational公司的产品,有一系列。可能你指的是Rose建模工具,它支持UML用来画用例图,序列图,状态图,类图等。可根据设计的类生成代码(包括多种语言)。还可以从代码反向生成类。如果你会UML,Rose则使你如虎添翼。Rose建模的图形可以帖到文档里,另外有一点,它比VISIO简单易学,显然功能不如VISIO强大。所以结论是:它是系统分析和设计的工具,也支持一点编码,用好ROSE的关键还是在于其它方面的功力。