一个看似简单但又难以理解的问题(高分请高手解决)!!!!急等!!!!

wxj81 2002-11-11 01:04:47
本程序是我编的编译原理的简单的pascal词法分析程序(可以运行):
问题是里面的void Display(char*[],float[],Tk[])函数打印不出char* Namel[50]
的内容(打印出来的也是错的),char* Namel[50]的在函数int InNamel(char*ch)被赋值.

main()函数里的注释"打开e:\\source.txt中的pascal源程序"source.txt中的pascal源程序如下:
program p;
var x1,x2 : integer;
begin
x1:=12;
x2:=x1+12*13;
end.

//==========================程序清单(可以运行)=======================
#include<iostream.h>
#include<String.h>
#include<conio.h>
#include<fstream.h>
struct Tk
{
unsigned long nam;
unsigned long IdAdd;
};
char*keyword[]={"program","begin","end","integer","real","read",
"write","bool","true","false","var","if","then",
"while","do"};

char*DT[]={"program","begin","end","integer","real","read",
"write","bool","true","false","var","if","then",
"while","do","<>","<=",">=",":=","/*","*/","+",
"-","*","/","=","<",">",".",";",":","'",",","(",")"};

class compile
{
public:
//扫描源代码
void Scanner();
//拼单词
void Identifier();
//读字符
void Read();
//跳过空格,回车,换行符
void NoBlank();
//constant函数用来判断实常数还是整常数,并将数放进Consl中
void Constant();
//判断是否字符
bool isLetter(char ch);
//判断是否数字
bool isDigit(char ch);
//在DT表中查找单词
int SerchDT(char *ch);
//将标志符放进Namel数组中
int InNamel(char*ch);
//将数字放进Consl数组中
int InConsl();
//将保留字,标志符,标点符号的地址放进Token数组中
void GenToken(int DtAdd,int NamConAdd);
void Display(char*[],float[],Tk[]);

static int c;
static int n;
static int t;
static int r;
char ch;
char name[10];
char* Namel[50];
float Consl[50];
Tk Token[100];
};
char buffer[100];
void main()
{
int i=0;
//打开e:\\source.txt中的pascal源程序
ifstream ar("e:\\source.txt");
while(!ar.eof())
{
buffer[i]=ar.get();
i++;
}
compile compiler;
compiler.Scanner();
compiler.Display(compiler.Namel,compiler.Consl,compiler.Token);
}

int compile::n=-1;
int compile::c=0;
int compile::t=0;
int compile::r=0;
void compile::Scanner()
{ cout<<"NAMEL table:"<<endl;
Read();
while (buffer[r]!=NULL)
{
NoBlank();
if(isLetter(ch))
{
Identifier();
//比较是否保留字
for(int i=0;i<35;i++)
if(strcmp(keyword[i],name)==0)
{
GenToken(SerchDT(name),0);
goto loop;
}
//将标识符放进Namel中,并将返回的该标识符的地址
//作为参数传给GenToken,该地址就是Namel[n]的n
//第一个参数设为1

GenToken(1,InNamel(name));
}
loop:
if(isDigit(ch))
{
Constant();
Read();
}
switch(ch)
{
case'(':GenToken(SerchDT("("),0);Read();break;
case')':GenToken(SerchDT(")"),0);Read();break;
case'+':GenToken(SerchDT("+"),0);Read();break;
case'-':GenToken(SerchDT("-"),0);Read();break;
case'*':GenToken(SerchDT("*"),0);Read();break;
case'/':GenToken(SerchDT("/"),0);Read();break;
case'=':GenToken(SerchDT("="),0);Read();break;
case'<':GenToken(SerchDT("<"),0);Read();break;
case'>':GenToken(SerchDT(">"),0);Read();break;
case'.':GenToken(SerchDT("."),0);Read();break;
case';':GenToken(SerchDT(";"),0);Read();break;
case',':GenToken(SerchDT(","),0);Read();break;
case':':Read();
if(ch=='=')
{
GenToken(SerchDT(":="),0);
Read();
}
else
{
GenToken(SerchDT(":"),0);
}
break;
}
}
}

void compile::Identifier()
{
int i=1;
name[0]=ch;
name[1]='\0';
Read();
while(isLetter(ch)||isDigit(ch))
{
name[i]=ch;
name[i+1]='\0';
i++;
Read();
}
}

void compile::Read()
{

ch=buffer[r];
r++;
}

void compile::NoBlank()
{
while(ch==' '||ch=='\n'||ch=='\r')
Read();
}

void compile::Constant()
{
int temp;
temp=ch-48;
Read();
while(isDigit(ch))
{
temp=temp*10+ch-48;
Read();
}
if(ch=='.')
{
Read();
if(isDigit(ch))
{
Consl[c]=temp+1.0*(ch-48)/10;
//c表示Consl[c]中的第c个数,3表示实常数
GenToken(3,c);
c++;
}
}
else
{
Consl[c]=temp;
//c表示Consl[c]中的第c个数,3表示整常数
GenToken(2,c);
c++;
}
}

bool compile::isLetter(char ch)
{
if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
return true;
else
return false;
}

bool compile::isDigit(char ch)
{
if(ch>='0'&&ch<='9')
return true;
else
return false;
}

int compile::SerchDT(char *ch)
{
static int k;
for(int i=0;i<sizeof(DT)/sizeof(*DT);i++)
if(strcmp(DT[i],ch)==0)
k=i;
return k;
}
int compile::InNamel(char*ch)
{
n++;
Namel[n]=ch;
return n;
}
void compile::GenToken(int DtAdd,int NamConAdd)
{
Token[t].nam=DtAdd;
Token[t].IdAdd=NamConAdd;
t++;
}

void compile::Display(char* namet[],float constt[],Tk tokent[])
{
cout<<"NAMEL table:"<<endl;
for(int i=0;i<n;i++)
cout<<namet[i]<<endl;
cout<<"CONSTANT table:"<<endl;
for(int z=0;z<c;z++)
cout<<constt[z]<<endl;
cout<<"TOKEN table:"<<endl;
for(int k=0;k<t;k++)
cout<<tokent[k].nam<<" "<<tokent[k].IdAdd<<end
...全文
15 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
wxj81 2002-11-11
  • 打赏
  • 举报
回复
zxm954712(zhangxiaoming) 高明
下午上完课回来给你们分,谢谢!!
心情很好:)
zxm954712 2002-11-11
  • 打赏
  • 举报
回复
当然不可以打印了,因为你的所有的Namel[n]所指的内存空间是存放name数组的值,当name数组的值变化的时候,所有的Namel[n]都会变化啊,改为如下:
int compile::InNamel(char*ch)
{
n++;
Namel[n] = new char[256];
strcpy(Namel[n], ch);
return n;
}
试试看,呵呵
YYBear 2002-11-11
  • 打赏
  • 举报
回复
嘿嘿,我也刚做完这个程序
keen_blue 2002-11-11
  • 打赏
  • 举报
回复
char* Namel[50];

当然Namel[50]不能正确显示拉
数组越界
你在InNamel()函数里面没有检查数组越界

在构建符号表的时候,为什么不用链表,动态分配,难道你能确信你解析的符号不超过50或者100

:)

69,381

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧