从识别符号向终结符过度时,从含有识别符号的规则入手,寻找所有规则中左部为识别符号的规则,然后搜索这些找到的规则的右部是否含有非终结符,若含有则从所有规则中找出左部为这个非终结符的规则,并标记,当搜完第一次后,循环查找具有标记的规则,按照上面的方式继续标记剩下的规则,直到没有新的规则被标记 退出 删除未标记的规则体
反方向同理……
说什么都不如看代码 下面是我写文法压缩时候写的压缩函数
void Mylist::condense(char spot,CString gettofun)
{
//condense with spot way
addsignal(spot,1)
for(int i=1i<7i++)
{
for(int j=0j<countj++)
{
if(readsignal(j)==i)
{
int rightlength=findright(j).GetLength()
for(int k=0k<rightlengthk++)
{
if(gettofun.Find(findright(j).GetAt(k))!=-1)
{
addsignal(findright(j).GetAt(k),i+1)
}
}
}
}
}
// unsigned the wordrule like s::=s*
bool caiding=false
for(int j=0j<countj++)
{
int rightlength=findright(j).GetLength()
for(int k=0k<rightlengthk++)
{
if(findleft(j)!=findright(j).GetAt(k))
caiding=true
}
if(caiding==false)
{signal(j,0)}
}
//format every node have been signed
for(int m=0m<countm++)
{
if(readsignal(m)!=0)
{
signal(m,1)
}
}
//decide which to begin
for(m=0m<countm++)
{
if((gettofun.FindOneOf(findright(m))==-1)&&(readsignal(m)!=0))
{
signal(m,2)
}
}
//right way condense
int q=2
for(int worry=0worry<10worry++){
for(int j1=0j1<countj1++)
{
if(readsignal(j1)==q)
{
for(int i1=0i1<counti1++){
//int right=findright(i1).GetLength()
for(int i2=0i2<findright(i1).GetLength()i2++)
{
if(findleft(j1)==findright(i1).GetAt(i2))
{
signal(i1,q)
}
}
}
}
}//^
}
}
这里说明一下
其中的findright(int i) 函数的功能是从第i条文法规则中找到它的右部 返回值为CString类型
signal(int i,int j)函数 是在第i条规则中找到它的标志位(即加标记)并把j放入这个标志位 以示本条规则已经做好了标记
addsignal(char i,int j) 则是找到左部名为i的规则,并标记他的标志位为j addsignalright同理
本函数传递进来的有两个参数 其中spot是识别符号Z,CString类型的是终结符号队列,包含所有已知的终结符号
在说明一点 wordrule是一个文法体class的对象 它是一个链表 每一个结点(node)为一个规则:
class node
{
public:
char leftwords
int signal
CString rightwords
node *next
public:
node(char,CString)
virtual ~node()
}
希望对你有所帮助
)在编写C语言源代码时,应该多使用注释,这样有助于对代码的理解。在C语言中有两种注释方式:
一种是以/*开始、以*/结束的块注释(block comment);
另一种是以//开始、以换行符结束的单行注释(line comment)。
可以使用/*和*/分隔符来标注一行内的注释,也可以标注多行的注释。例如,在下列的函数原型中,省略号的意思是 open() 函数有第三个参数,它是可选参数。注释解释了这个可选参数的用法:
int open( const char *name, int mode, … /* int permissions */ )
可以使用//插入整行的注释,或者将源代码写成两列分栏的格式,程序在左列,注释在右列:
const double pi = 3.1415926536 // pi是—个常量
在 C99 标准中,单行注释正式加入C语言,但是大部分编译器在 C99 之前就已经开始支持这种用法。有时候,其被称作“C++风格”的注释,但实际上,其源自于C的前身 BCPL。
在引号中,如果采用/*或//分隔一个字符常量或字符串字面量(string literal),它们都不会被视为注释的开始。例如,下面语句就没有注释:
printf("Comments in C begin with /* or //.\n" )
预处理器仅通过检查注释的结束符来检测注释中的字符,因此,不能嵌套块注释。然而,可以使用/*和*/注释包含单行注释的源代码:
/* 暂时注释掉这两行:
const double pi = 3.1415926536 // pi是一个常量
area = pi * r * r // 计算面积
暂时注释到此 */
如果想要注释掉包含块注释的部分程序,可以使用条件预处理命令:
#if 0
const double pi = 3.1415926536 /* pi是一个常量 */
area = pi * r * r /* 计算面积 */
#endif
预处理器会把每个注释都替换成一个空格。因此,min/*max*/Value变成两个标记min Value。
所有教程
直接在该行需要注释的地方加上"//"即可。
可以使用/*和*/分隔符来标注一行内的注释,也可以标注多行的注释。例如,在下列的函数原型中,省略号的意思是 open() 函数有第三个参数,它是可选参数。
注释解释了这个可选参数的用法:
int open( const char *name, int mode, … /* int permissions */ );
代码具有较好的可移植性
C语言是面向过程的编程语言,用户只需要关注所被解决问题的本身,而不需要花费过多的精力去了解相关硬件,且针对不同的硬件环境,在用C语言实现相同功能时的代码基本一致,不需或仅需进行少量改动便可完成移植,这就意味着,对于一台计算机编写的C程序可以在另一台计算机上轻松地运行,从而极大的减少了程序移植的工作强度。
以上内容参考:百度百科-C语言
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)