C#WinForm实现不规则窗体

这个纯属娱乐,因为其实用的不是太多,因为非主流,非标准的界面不符合用户的体验,不符合可用性功能的某一条HE规则。 为了完成这个效果,首先需要自己动手画个你需要的界面出来,界面边缘需要是一种可以很好区别的颜色,比如纯蓝色,因为实现不规则窗体是让C#使边缘颜色透明化来实现的,所以需要唯一识别。因为我用的图是一张灰色的图,我然后圈了一个蓝色的边缘。 刚开始的图; 然后新建windows应用程序。创建windows窗体并设置窗体基本属性。 (1)将 FormBorderStyle 属性设置为 None。 (2)将窗体的 BackgroundImage 属性设置为先前创建的位图文件。不必将文件添加到项目系统中;这将在指定该文件作为背景图像时自动完成。 (3)将 TransparencyKey 属性设置为位图文件的背景色,本例中为蓝色。(此属性告诉应用程序窗体中的哪些部分需要设置为透明。 ) 上面两个步骤已经完成了不规则窗体自身显示效果的制作。 有人说在24位色以下的环境中可以显示正常,但在24位色以上时黄色背景不能消失,所以上述不能胜任24位色以上环境。但我看到了一种解决方法,那就是先将背景图片添加到资源文件,然后在窗体构造时为窗体设置背景图片: private void Form1_Load(object sender, EventArgs e){ Bitmap bmp = Properties.Resources.form2; bmp.MakeTransparent(Color.Blue); // bmp.MakeTransparent(Color.FromArgb(2,2,2));如果rgb则是这样用 this.BackColor = Color.Blue; this.BackgroundImage = bmp; this.TransparencyKey = Color.Blue; } 实测是可以的。 然后就是为窗体添加移动、关闭、最大最小化的事件。代码直接给出 private bool isMouseDown = false; //记录鼠标是否被按下 private Point position; //记录鼠标位置 private void Form1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { int x = -e.X; int y = -e.Y; position = new Point(x, y); isMouseDown = true; } } private void Form1_MouseMove(object sender, MouseEventArgs e) { if (isMouseDown) { Point newPosition = Control.MousePosition; newPosition.Offset(position); this.Location = newPosition; } } private void Form1_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { isMouseDown = false; } } 还有其他一些比如关闭按钮的添加,都很简单,直接添加一个button,事件里写,两个选一个。 this.Close();//关闭此窗体 Application.Exit();//退出应用程序 我最终的效果是个圆,可以看到,锯齿很明显,我想要效果好的话,那个位图得好好设计。这个只是演示。。所以。。还有一种方法是链接1中提供的,有兴趣的可以试试。 工程源码下载:IrregularForm.7z 参考: http://www.cnblogs.com/KissKnife/archive/2006/10/02/520116.html http://allancandy.cnblogs.com/archive/2005/09/01/227814.html

2012-06-21 · 1 min · bystander

SASS用法指南

作者: 阮一峰 日期: 2012年6月19日 学过CSS的人都知道,它不是一种编程语言。 你可以用它开发网页样式,但是没法用它编程。也就是说,CSS基本上是设计师的工具,不是程序员的工具。在程序员眼里,CSS是一件很麻烦的东西。它没有变量,也没有条件语句,只是一行行单纯的描述,写起来相当费事。 很自然地,有人就开始为CSS加入编程元素,这被叫做“CSS预处理器”(css preprocessor)。它的基本思想是,用一种专门的编程语言,进行网页样式设计,然后再编译成正常的CSS文件。 各种"CSS预处理器"之中,我自己最喜欢SASS,觉得它有很多优点,打算以后都用它来写CSS。下面是我整理的用法总结,供自己开发时参考,相信对其他人也有用。 ============================================ SASS用法指南 作者:阮一峰 一、什么是SASS SASS是一种CSS的开发工具,提供了许多便利的写法,大大节省了设计者的时间,使得CSS的开发,变得简单和可维护。 本文总结了SASS的主要用法。我的目标是,有了这篇文章,日常的一般使用就不需要去看官方文档了。 二、安装和使用 2.1 安装 SASS是Ruby语言写的,但是两者的语法没有关系。不懂Ruby,照样使用。只是必须先安装Ruby,然后再安装SASS。 假定你已经安装好了Ruby,接着在命令行输入下面的命令: gem install sass 然后,就可以使用了。 2.2 使用 SASS文件就是普通的文本文件,里面可以直接使用CSS语法。文件后缀名是.scss,意思为Sassy CSS。 下面的命令,可以在屏幕上显示.scss文件转化的css代码。(假设文件名为test。) sass test.scss 如果要将显示结果保存成文件,后面再跟一个.css文件名。 sass test.scss test.css SASS提供四个编译风格的选项: nested:嵌套缩进的css代码,它是默认值。 expanded:没有缩进的、扩展的css代码。 compact:简洁格式的css代码。 compressed:压缩后的css代码。 生产环境当中,一般使用最后一个选项。 sass –style compressed test.sass test.css SASS的官方网站,提供了一个在线转换器。你可以在那里,试运行下面的各种例子。 三、基本用法 3.1 变量 SASS允许使用变量,所有变量以$开头。 $blue : #1875e7; div { color : $blue; } 如果变量需要镶嵌在字符串之中,就必须需要写在#{}之中。 $side : left; .rounded { border-#{$side}-radius: 5px; } 3.2 计算功能 SASS允许在代码中使用算式: body { margin: (14px/2); top: 50px + 100px; right: $var * 10%; } 3.3 嵌套 SASS允许选择器嵌套。比如,下面的CSS代码: div h1 { color : red; } 可以写成: div { hi { color:red; } } 属性也可以嵌套: p { border-color: red; } 可以写成: p { border: { color: red; } } 注意,border后面必须加上冒号。 3.4 注释 SASS共有两种注释风格。 标准的CSS注释 /* comment */ ,会保留到编译后的文件。 单行注释 // comment,只保留在SASS源文件中,编译后被省略。 四、代码的重用 4.1 继承 SASS允许一个选择器,继承另一个选择器。比如,现有class1: .class1 { border: 1px solid #ddd; } class2要继承class1,就要使用@extend命令: .class2 { @extend .class1; font-size:120%; } 4.2 Mixin ...

2012-06-19 · 2 min · bystander

gif反转工具

首先看下效果图: 然后是两张gif的对比 //原本图是正着走的 //处理后是倒着走的 gif是动态的嘛。然后我昨天和一个朋友聊天的时候发了一串相同的gif图,然后看着千篇一律的东西。我想能不能写个程序实现gif的初始状态不同呢。什么意思呢。我们知道,gif是由帧构成的,我想实现的功能是比如一个gif共有十帧,那么我写出来的程序能够生成10个gif文件,分别对应不同的初始状态来进行循环。后来一想,gif帧太多的话,比较慢,而且也不实用,于是决定简化一下,只做一个反转工具,比如一个gif是从左到右播放的,通过这个成功可以生成一个相同的gif图,不过是倒着播放的。 思路很简单,就是先把gif分解成很多帧,然后对帧进行合并,合并帧之前把帧的位置反转一下就可以了。因为我自己对图像处理的知识不懂,只想到了思路,所以这些功能都要找些资料,然后修改,测试。 分割帧的代码如下 //解码gif图片 public List<string> GetFrames(string pPath, string pSavedPath) { Image gif = Image.FromFile(pPath); FrameDimension fd = new FrameDimension(gif.FrameDimensionsList[0]); //获取帧数(gif图片可能包含多帧,其它格式图片一般仅一帧) int count = gif.GetFrameCount(fd); List<string> gifList=new List<string>(); //以Jpeg格式保存各帧 for (int i = 0; i < count; i++) { gif.SelectActiveFrame(fd, i); gif.Save(pSavedPath + "\\frame_" + i + ".png", ImageFormat.Png); gifList.Add(pSavedPath + "\\frame_" + i + ".png"); } return gifList; } 可以看到,返回了一个包含所有生成的帧地址的list列表。然后就是使用gifList作为参数来合并了。 //获取系统临时目录存放解码后的png图片 string temppath = System.Environment.GetEnvironmentVariable("TEMP"); List<string> gifList = GetFrames(tBoxFile.Text, temppath); gifList.Reverse(); String outputFilePath = "new.gif"; AnimatedGifEncoder ae = new AnimatedGifEncoder(); ae.Start(outputFilePath); ae.SetDelay(100); // 延迟间隔 ae.SetRepeat(0); //-1:不循环,0:总是循环 播放 for (int i = 0, count = gifList.Count; i < count; i++) { ae.AddFrame(Image.FromFile(gifList[i])); } ae.Finish(); MessageBox.Show("成功!新文件已保存在同目录"); 这里面使用了AnimatedGifEncoder这个类,这是Gif.Components.dll动态连接库里的类(此库开源,文末给出地址),是我在codeProject上找到的。首先我把gifList反转,然后合并保存到同目录。中间生成的帧为了方便我保存到了temp目录。 本来这个库里是分割gif的功能的。但是我实际测试后发现效果非常差,图片黑条泛滥,根本没法看。所以还是使用上面那段代码,相关代码我依然保存在工程里,有兴趣可以自己测试。 明天四级考试,求人品。。 项目源码:gif反转工具 参考: C#图片处理:获取GIF 动画图片中的各个帧 NGif, Animated GIF Encoder for .NET

2012-06-15 · 1 min · bystander

属性文法

 我们知道,许多编译程序采用属性文法和语法制导翻译方法对语义处理工作进行比较规范和抽象的描述。 而一个属性文法包含一个上下文无关文法和一系列文法规则,语义规则是指:对于文法的每个产生式都配备了一组属性的计算规则 语义规则附在文法的每个产生式上,而语法制导翻译是指在语法分析过程中,完成附加在所使用的产生式上的语义规则描述的动作。 ·语法制导:基于语法分析中用到的文法产生式 ·翻译:完成语义分析的各项功能,不仅指生成中间代码 形式上讲,一个属性文法是一个三元组,A=(G,V,F),其中G是一个上下文无关文法;V是有穷的属性集,每个属性与文法的一个终结符或非终结符关联,属性加工的过程即是语义处理的过程。F是关于属性的属性断言或一组属性的计算规则(称为语义规则)。断言或语义规则与一个规则式关联,只引用该规则式左端或右端的终结符或非终结符关联的属性。形式化的东西看看就好,后面给出具体例子分析。 既然称之为属性文法,那么什么属性呢。这些属性代表与文法符号相关信息,比如它的类型、值、代码序列、符号表内容等等。属性与变量一样,可以进行计算和传递。可以类比我们平时写代码时候一些成员变量。。属性又分为综合属性和继承属性。 n在一个属性文法中,对应于每个产生式A→a都有一套与之相关联的语义规则,每条规则的形式为: b:=f(c1,c2,…,ck),只有在已知 c1-ck 值的基础上,才能计算属性值 b, 称属性 b 依赖于属性 c1-ck,至于c1-ck依赖于哪个,就得看由c1-ck在左侧的规则了。也就是看下面的规则了。 这里,f是一个函数,而且或者 1. b是A的一个综合属性并且c1,c2,…,ck是产生式右边文法符号的属性,或者 2. b是产生式右边某个文法符号的一个继承属性并且c1,c2,…,ck 是A或产生式右边任何文法符号的属性。 属性b依赖于属性c1,c2,…,ck。 属性文法中常用记号N·t表示与非终结符号N相关联的属性t。 注意:¨终结符只有综合属性,由词法分析器提供 ¨非终结符既可有综合属性也可有继承属性,文法开始符号的所有继承属性作为属性计算前的初始值 ¨在语法树中,一个结点的综合属性的值由其子结点的属性值确定。一个结点的继承属性由此结点的父结点和/或兄弟结点的某些属性确定 根据包含的属性类型,属性文法分为:S-属性文法和L-属性文法 S-属性文法是仅包括综合属性的属性文法;L -属性文法是包括综合属性和继承属性的属性文法。 给出一个简单的实例说明上面的内容: 考虑非终结符A,B和C,其中,A有一个继承属性a和一个综合属性b,B有综合属性c,C有继承属性d。产生式A→BC可能有规则 C.d:=B.c+1 A.b:=A.a+B.c 而属性A.a和B.c在其它地方计算 为什么是这样的,因为此时A就是A,B是X1,C是X2,对于d来说,他是产生式右部C的一个属性,c是右部B的属性,属性d依赖于属性c,和1,所以它是C的继承属性,对于c来说,他是产生式右部B的一个属性,但是c不依赖于d,而是d依赖于c所以c属性类型无法确定,对于b,他是A的一个属性,并且a是A的属性,c是产生式右部的属性,所以b是A的综合属性,而对于a,因为不能确定a属性依赖于那个属性,所以。无法得知。从上面我可以得出一个规律,对于一个属性规则来说,一条规则只能确定其左侧的属性类型,而右侧的属性需要由一个由他在左侧的规则来确定。比如,可以看到上面的规则中,c和a都不能确定,就是因为在规则右侧。 此部分可能理解不够深刻,如有错误欢迎指正。 参考: http://jpkc.hdu.edu.cn/computer/byyl/online/5-2.htm http://metc.gdut.edu.cn/compile/nandian/n-8.htm

2012-06-08 · 1 min · bystander

LR(1)项目集规范簇的构造

 首先我们知道LR(0)的项目的形式是[A→α·β ]这样的.而在LR(1)中的项目形式是[A→α·β ,a ],其中A→α·β 为LR(0)项目,称为心,a为终结符或#,称为向前搜索符。对归约项目[A→α·,a],仅当前输入符号是a时,才能用A→α进行归约。一会将会看到具体的例子。 课本上给出的规则是:我将要对照着规则来说明,这里要强调一下,",‘在这里是分隔符。不是终结符。他是一个标志, 以S′→·S,#属于初始项目集中,把’#‘号作为向前搜索符,表示活前缀为γ(若γ是有关S产生式的某一右部)要归约成S时,必须面临输入符为’#‘号才行。因此对初始项目S′→·S,# 求闭包后再用转换函数逐步求出整个文法的LR(1)项目集族。具体构造步骤如下: (1) 构造LR(1)项目集的闭包函数。 a) I 的任何项目都属于CLOSURE(I) b) 若有项目[A→α·Bβ,a ]属于CLOSURE(I),B→γ是文法中的产生式,β∈V*,b∈FIRST(βa), 则[B→·γ,b]也属于CLOSURE(I)中。 c) 重复b)直到CLOSURE(I)不再增大为止。 (2) 转换函数的构造 LR(1)转换函数的构造与LR(0)的相似,GO(I,X)=CLOSURE(J) 其中I是LR(1)的项目集,X是文法符号: J={任何形如[A→αX·β,a]的项目 | [A→α·Xβ,a]∈I} 例如下列文法G′为: (0) S′→S (1) S→aAd (2) S→bAc (3) S→aec (4) S→bed (5) A→e 构造他的LR(1)项目集规范簇。 以I0=CLOSURE(S′→·S,#)开始。运算。若有项目[A→α·Bβ,a ]属于CLOSURE(I),B→γ是文法中的产生式,β∈V*,b∈FIRST(βa), 则[B→·γ,b]也属于CLOSURE(I)中。此时,我们可以把S看成B,#看成a,然后需要求FIRST集合,此时没有β,a为#,所以FIRST(#)中只有一个b=#,而S有四个产生式。所有四个产生式加上#都是在I0中,最终求得的I0项目集为 { S′→·S,# S→·aAd,# S→·bAc,# S→·aec,# S→·bed,# } 然后使用GO函数来构造I1,从J={任何形如[A→αX·β,a]的项目 | [A→α·Xβ,a]∈I}我们可以知道I1的核(最初的产生式)就是这里的J,然后呢。X是I(也就是我们的I0)中的·后面的符号,也就是输入符。。可以看到在I0中,X可以为S,a,b,我们先以I1=GO(I0,S)=CLOSURE( S′→S·,# ),注意,·号已经前进了。因为J是I输入进一的项目,求I1,发现·后面没符号了,所以闭包就是他自己了。最终求得的I1的项目集为: {S′→S·,# } 我们上一步是用的I1=GO(I0,S)来求得,我们求I2的时候使用GO(I0,a)来求,此时X就是a了。然后我们吧I0中符合的项目中的·后移一位得到J然后对J求闭包,就是I2了。此处J=S→a·Ad,# 和S→a·ec,# I2=GO(I0,a)=CLOSURE(S→a·Ad,# S→a·ec,#),然后又回到了求闭包了。 对于S→a·ec,#,因为输入符下一位是一个终结符,也就是说没有B→γ这样的产生式,所以这个就不用继续向下求闭包了,闭包就是他自己嘛。然后关键是S→a·Ad,# 此处的A相当于规则中的B,d相当于规则中的β,A→e存在。为了确定这个心的向前搜索符,我们根据规则需要求b∈FIRST(βa),这里也就是求First(d#),显然结果为b=d,规则中指出[B→·γ,b]也属于CLOSURE(I),所以可以确定A→·e,d也在I2中。。 最终I2的项目集为 { S→a·Ad,# S→a·ec,# A→·e,d } 到这里,关键点就说完了。只需要继续求GO(I0,b),然后求GO(I1,X),GO(I2,X)等等。X的确定前面已经说了,就是I1,I2的·后面的符号。就行了。。当然像此处的I1,·后面已经没付好了,所以GO(I1,X)就不用求了。。 这种东西还是要自己手动练习的。所以我给出最终的全部项目集规范簇,大家按照这个步骤来做一做。看看结果对不对吧。 I0: S′→·S,# S→·aAd,# S→·bAc,# S→·aec,# S→·bed,# I1: S′→S·,# I2: S→a·Ad,# S→a·ec,# A→·e,d I3: S→b·Ac,# S→b·ed,# A→·e,c I4: S→aA·d,# I5: S→ae·c,# A→e·,d I6: S→bA·c,# I7: S→be·d,# A→e·,c I8: S→aAd·,# I9: S→aec·,# I10:S→bAc·,# I11:S→bed·,# 构造的过程很繁琐。有点暴力计算的意思。不过,真正算起来步骤还是比较少的。

2012-06-02 · 1 min · bystander

比较HE和Think Aloud可用性测试

首先,HE和Think Aloud 都是两用可用性测试的方法,HE,也就是这个启发式评估可以在设计的早期阶段(比如草稿)就开始使用,并且不需要太多的其他步骤。而Think Aloud则更多建立在已经设计出来的原型系统上。需要更多的步骤。这两个各有利弊。互相协作。才能更好嘛,有些问题,HE可以发现,有些则只有Think Aloud可以发现。 1.Many Usability Aspects Identified in HE are Confirmed in Think-Aloud Usability Tests 许多可用性方面的问题可以在HE中识别。然后在Think Aloud测试中被确认。 2.When HE Predictions are not Confirmed by Think-Aloud Usability Tests 当HE预测了问题但是Think Aloud中,并没有发现。这种情况下。请相信Think Aloud测试。因为用户是王道。数据比预测更准确。 3.“False Alarms” vs. True Problems 假警告vs真问题,这个举个例子,在对话框中,有三个按钮。OK ,Apply和Cancel ,虽然HE规则预测了这个迷惑性。但是进行Think Aloud测试的时候,并没有这个问题,原因是用户就没想过这个事,他只按ok,但这并不能避免问题,或者说似乎这个问题并不是个问题,还有一种情况,比如HE规则中的文档帮助的问题,可能用户在测试的时候就没打开文档。这就需要HE来评估了。所以,这种情况下,还是应该好好分析一下HE给出的评估来改进系统。 4.Think-Aloud Usability Tests Can Show Things HEs Can’t Show Think Aloud测试可以展示HE没有发现的问题。 HE规则因为是建立在早期草稿原型上的。并不是真实情况,他只是在早期给出设计上的问题,他不能预测真实系统的问题,比如程序运行速度非常慢,以至于用户难以忍受。这就需要Think Aloud才能发现了。 基本上SSD4就讲了这么些东西了。四篇文章四点写到7点。。基本上算是写完了。工科男求安慰。。

2012-05-29 · 1 min · bystander

UAR报告的简单说明

UAR报告由以下几个部分构成。就这个例子简单说一下。 Example UAR — Time Zone ListBox Is Not Good //标题 UAR Identifier //问题编号,从1开始,每个问题都这样的格式来说明,就构成了UAR报告 HE18—Problem //后面这个problem表示有问题,也可以是Good,表示这部分很好。没问题。 Succinct description: //简短的描述 Time Zone pull-down ListBox provides too much irrelevant information. Evidence for the aspect: //违反了哪条规则,共有十条规则。 Heuristic: Aesthetics and minimalist design **Interface aspect: ** The pull-down ListBox has 50 lines of information—in very small font. There are many competing items of information to visually search, the vast majority of which are irrelevant to any one user’s particular task of finding a single desired time zone [![](/images/ "uar")](http://seqcc.icarnegie.com/content/SSD/SSD4/3.1/normal/pg-creatng-evaltng-interfaces/pg-crt-eval-list-combo/pg-he-clean-beauty/Ex5.png)In addition, the information is structured as follows:The string "[GMT " begins each line (which means Greenwich Mean Time). If the time zone is behind GMT, then a "-" indicates this fact, which is followed by the number of hours and minutes the time zone is behind GMT. If the time zone is ahead of GMT, a "+" is used instead. Finally, some words follow the GMT offset, which are either city or country names, or the names of regions.  The presentation of this structured information violates the aesthetics and minimalist design heuristic because the structure is not preserved visually from item to item. For example, the words are not always lined up vertically; see the entries for: ...

2012-05-29 · 3 min · bystander

10条可用性准则(Heuristics)

SSD4第二单元其实就讲了这么一点东西,包括一点VB的控件常识 可用性测试(Usability testing),是一项通过用户的使用来评估产品的技术,由于它反应了用户的真实使用经验,所以可以视为一种不可或缺的可用性检验过程[1]。也就是说,可用性测试是指让用户使用产品(服务)的设计原型或者成品,通过观察,记录和分析用户的行为和感受,以改善产品(服务)可用性的一系列方法。它适用于产品(服务)前期设计开发,中期改进和后期维护完善的各个阶段,是用户中心设计的思想的重要体现。 10条可用性准则(Heuristics) These are ten general principles for user interface design. They are called “heuristics” because they are more in the nature of rules of thumb than specific usability guidelines. 1.Visibility of system status——系统状态的可见性 The system should always keep users informed about what is going on, through appropriate feedback within reasonable time. 系统应该始终在合理的时间以适当的反馈信息让用户知道系统正在做什么。 2.Match between system and the real world——系统和现实世界之间的吻合 The system should speak the users’ language, with words, phrases and concepts familiar to the user, rather than system-oriented terms. Follow real-world conventions, making information appear in a natural and logical order. 系统应该用用户熟悉的词,短语和概念来说用户的语言,而不是用面向系统的术语。遵循现实世界中的惯例,让信息以自然的合乎逻辑的次序展现在用户面前。 3.User control and freedom——用户控制和自由 Users often choose system functions by mistake and will need a clearly marked “emergency exit” to leave the unwanted state without having to go through an extended dialogue. Support undo and redo. 用户经常错误地选择系统功能,所以在不需要查看由于误操作而延伸出来地对话的情况下有一个明显地标志为“紧急退出”的操作来离开不想要的状态。另外,系统需要支持“撤销操作”和“重做”的功能。 4.Consistency and standards——一致性和标准 Users should not have to wonder whether different words, situations, or actions mean the same thing. Follow platform conventions. ...

2012-05-29 · 2 min · bystander

修改Windows系统软件默认安装路径

 作为一个完全不能容忍windows默认程序都往C:\Program Files\目录里安装的人。每次安装软件的时候,都得手动一个个改到D:\Program Files里。安装软件多了。就hold不住了。 其实可以通过注册表使得所有安装程序默认安装到其他盘的。将下列内容保存到一个文本文件里,命名为Mo.reg。然后运行即可。以后安装的程序就会默认安装到D盘的Program Files目录了。你也可以根据需要自行修改 Windows Registry Editor Version 5.00 ;修改Windows系统软件默认安装路径 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion] “ProgramFilesDir”=“D:\Program Files” 效果如下图,安装程序已经默认到D盘了 update:已知后遗症,我在这样实践了以后,发现vs2010的.net framework 4将会丢失。也就是说就不能新建.net framework 4项目了,具体不明,可能是我当初把VS一部分安装到D盘的缘故,应该可以通过重新安装vs解决,如果你不想折腾。把注册表改回去就可以了。

2012-05-17 · 1 min · bystander

一个简单实例的LR分析过程

 经过前面两篇文章。已经讲清楚了LR语法分析中最重要的分析表的构造过程。先补充一个小问题,就是LR(0)项目的分类 根据圆点所在的位置和圆点后是终结符还是非终结符或为空把项目分为以下几种: 移进项目: 形如 A→α .a β ,a是终结符, a ,b∈V* 以下同 待约项目:A→α .B β , 其中B是非终结符 归约项目:A→α . 表明产生式已分析完成。 接受项目:形如 S’→S . 特别的。A→ε的LR(0)项目只有A→ • 是归约项目 因为LR分析表的构造前面两篇文章已经讲的很清楚了,所以这个题目重要是解释一下如何使用分析表来构造,分析表的构造也许你得自己参考前面两篇文章来构造了。题目来自网络。 好,下面看题目,已知文法G[S]: (1) S → aAcBe (2) A → b (3) A → Ab (4) B → d 写出对输入串 abbcde#的LR分析 过程。 在分析的时候,因为我们的手工分析,所以还需要一个表来记录我们的步骤。否则记不住啊。该表共需7列。行数不定。做到哪是哪。 步骤 符号栈 输入符号栈 动作 状态栈 ACTION GOTO 其中,步骤就是从1向下递增。符号栈用来保存运算中的结果,初始为#,输入符号栈保存输入串,初始值为给定的。动作里面就是用来注释是进行移进,还是规约。状态栈就是保持LR分析表的那个状态了。Action 和Goto同理 通过前两篇文章的步骤,此题可以构造出如下的一张LR分析表 分析表中有Si和rj大家都知道的。s是shift的缩写,也就是移进,r是reduce的缩写,也就是规约。规约是推导的逆操作,大家都懂。 先来看看在进行分析的时候s和j操作的规则 Si:移进,把i移入到状态栈,把a移入到文法符号栈。其中i,j表示状态号。 ri:归约,用第i个产生式归约,同时状态栈与符号栈退出相应个符号,并把GOTO表相应状态和第i个产生式的左部非终结符入栈。 文法中有A→β的产生式,若β的长度为r(即|β|=r),则从状态栈和文法符号栈中自栈顶向下去掉r个符号,即栈指针P减去r。并把A移入文法符号栈内,Sj=GOTO[Si,A]移进状态栈,其中Si为修改指针后的栈顶状态。 当归约到文法符号栈中只剩文法的开始符号S时,并且输入符号串已结束即当前输入符是’#’,则为分析成功。 然后使用我们将要使用的辅助表来分析吧,为了简单。我还是直接给出答案。然后分析一下典型的情况。 第一步,符号栈中是#,输入符号串就是给定的要分析的串,状态栈因为从0开始,所以状态栈直接填0,大家都知道,LR分析是从左到右扫描的。所以心里想着一根指针p,p首先指向输入串的a,然后我们查分析表的(0,a),0就是状态0,a就是指针的当前字符。分析表中的(0,a)是s2,填入第一步的action,并且动作列填入移进,根据规则,将2入状态栈,a入符号栈, 进入第二步,指针p肯定要前进一步了,所以输入符号串就进入b了。此步同上一步,不多解释。 关键是进入第三步后,此时,符号栈中为#ab,输入符号串是bcde#,状态栈是024,此时去查表,差的是(4,b),4是状态栈顶,b是p指针的当前位置。发现是r2,根据规则,用第二条产生式(2) A → b来规约。把动作栏先填了,同时状态栈与符号栈退出相应个符号,也即是说,把状态栏的栈顶4,退出来,同时符号栈的b也退出,心里想着,不填表,并把GOTO表相应状态和第i个产生式的左部非终结符入栈。Goto表需要查的是(2,A)=3,2是r2的2,A是第二个产生式的左部嘛。所以,就把3入状态栈,A入符号栈。 后面的都是一样的。不解释了。要想学懂编译原理。多动手是必需的。你也手工试试吧。 参考: http://leaver.me/archives/574.html http://leaver.me/archives/548.html

2012-05-14 · 1 min · bystander