用C和C++编的简单词法分析器,执行结果不同?

虫洞 2009-03-08 08:52:21
初学编译原理,用C++编了简单的词法分析器
发现执行结果比原版用C编的不全
我主要修改
文件的定义:FILE *fp;改为ifstream fp("file.txt");
获取字符:ch=fgetc(fp);改为ch=fp.get();
文件指针回退一格:fseek(fp,-1L,1);改为fp.seekg(-1,ios::cur);

C源文件[code=#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<malloc.h> /* malloc()等 */
#include<limits.h> /* INT_MAX等 */
#include<stdlib.h> /* atoi() */
#include<io.h> /* eof() */
#include<math.h> /* floor(),ceil(),abs() */
#include<process.h> /* exit() */
#include<time.h>
#define MAX 20
typedef struct //二元组
{
int syn; //种别编码
char value[MAX]; //值
}WS;
char ch;
FILE *fp;

void getbc() //检查ch是否为空白符,是的话,继续取下一个字符,直到不为空
{
while(ch==' ') ch=fgetc(fp);
}

int letter() //判断ch是否为字母
{
if((ch>='A')&&(ch<='Z')||(ch>='a')&&(ch<='z')) return 1;
else return 0;
}

int digit() //判断ch是否为数字
{
if((ch>='0')&&(ch<='9')) return 1;
else return 0;
}

int reserve(char *token) //查关键字表,判断token中的字符串是否为关键字
{
int key=10,i;
char WORDS_KEY[8][20]={"main","int","char","if","else","for","while","void"};
for(i=0;i<8;i++)
if(strcmp(token,WORDS_KEY[i])==0) {key=i+1; break;}
return key;
}

void error() //错误调用函数
{
printf("There has some unlawful words!");
}

print(WS *wd) //打印函数
{
printf("<%d,%s>",wd->syn,wd->value);
}
WS scaner() //扫描函数,主要算法
{
char token[20];
WS wd;
int c;
int i=0;
ch=fgetc(fp);
getbc(fp);
if(letter()) //是否为字母,是的话继续取字符,直到取的词不是字母或数字。调用reserve(char *token)判断是否为关键字。
{
while(letter()||digit())
{
token[i]=ch;
ch=fgetc(fp);
i++;
}
token[i]='\0';
fseek(fp,-1L,1); //退一个字符
c=reserve(token);
if(c!=10) { wd.syn=c;strcpy(wd.value,token); return wd;}
else { wd.syn=10;strcpy(wd.value,token);return wd;}
}
else if(digit()) //是否为数字,是的话继续取字符,直到取的词不是数字。
{
while(digit())
{
token[i]=ch;
ch=fgetc(fp);
i++;
}
fseek(fp,-1L,1);
token[i]='\0';
wd.syn=11;strcpy(wd.value,token);return wd;
}
else
{
switch(ch) //判断可识别字符
{
case '+': ch=fgetc(fp);
if(ch=='+') {wd.syn=13;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;}
fseek(fp,-1L,1);
wd.syn=25;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case '-': wd.syn=14;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case '*': wd.syn=15;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case '/': ch=fgetc(fp);
if(ch=='*')
{
while(1)
{
ch=fgetc(fp);
if(ch=='*')
{
ch=fgetc(fp);
if(ch=='/')
break;
}
}
wd.syn=-1; return wd;
break;
}
fseek(fp,-1L,1);wd.syn=16;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case '<': ch=fgetc(fp);
if(ch=='='){ wd.syn=26;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;}
fseek(fp,-1L,1);
wd.syn=18;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case ';': wd.syn=24;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case '(': wd.syn=20;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case ')': wd.syn=21;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case '{': wd.syn=22;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case '}': wd.syn=23;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case ',': wd.syn=19;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case '=': wd.syn=17;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
default : wd.syn=-1; return wd;break;
}
}
}
main()
{
WS wd;
ch=0;
if((fp=fopen("file.txt","r+"))==NULL) printf("文件打开失败");
while(ch!='#') //文件以"#"结束
{
wd=scaner(fp);
if(wd.syn!=-1)
{ print(&wd);printf("\n");}
}
fclose(fp);
getch();
}][/code]
...全文
240 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
虫洞 2009-03-09
  • 打赏
  • 举报
回复
自己查了
原来是文件没用二进制方式打开
这样使用tellg()和seekg()是有影响的
把ifstream fp("file.txt");改为ifstream fp("file.txt",ios::in|ios::out|ios::binary);

还发现用get()和输入流 >> 输入会自动跳过空格
我是应该换成read()
还是正好利用它来设置词法分析器


  • 打赏
  • 举报
回复
我在 fp.seekg(-1,ios::cur); //退一个字符
前加文件当前指针long p=fp.tellg();
发现有问题
每次获取一个标识符后跳好几个指针

保证你跳的时候指针转换为char *型,一般就是一字节一字节跳了.
taoyanxu1989 2009-03-09
  • 打赏
  • 举报
回复
mark
chaojiew 2009-03-09
  • 打赏
  • 举报
回复
http://blog.vckbase.com/bruceteen/archive/2007/05/14/18761.html
虫洞 2009-03-09
  • 打赏
  • 举报
回复
我在 fp.seekg(-1,ios::cur); //退一个字符
前加文件当前指针long p=fp.tellg();
发现有问题
每次获取一个标识符后跳好几个指针

怎样在调试监视当前文件指针的每一步变化?
antss 2009-03-08
  • 打赏
  • 举报
回复
哥们,你有电子版的吗?龙书,我也想要买,可是最近...

89太贵了.

虽然是好书.有电子版的没?

tangshuiling 2009-03-08
  • 打赏
  • 举报
回复

有时间帮你看看,这种程序理念挺简单的就是很繁琐
chin_chen 2009-03-08
  • 打赏
  • 举报
回复
哇。
虫洞 2009-03-08
  • 打赏
  • 举报
回复
file.txt文件
void main()
{
int a,b;
a=0;b=1;
int c=a+b;

}
#
虫洞 2009-03-08
  • 打赏
  • 举报
回复
C++源文件
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
#define MAX 20

typedef struct //二元组
{
int syn; //种别编码
char value[MAX]; //值
}WS;
char ch;
ifstream fp("file.txt");

void getbc() //检查ch是否为空白符,是的话,继续取下一个字符,直到不为空
{
while(ch==' ') ch=fp.get();
}

int letter() //判断ch是否为字母
{
if((ch>='A')&&(ch<='Z')||(ch>='a')&&(ch<='z')) return 1;
else return 0;
}

int digit() //判断ch是否为数字
{
if((ch>='0')&&(ch<='9')) return 1;
else return 0;
}

int reserve(char *token) //查关键字表,判断token中的字符串是否为关键字
{
int key=10,i;
char WORDS_KEY[8][20]={"main","int","char","if","else","for","while","void"};
for(i=0;i<8;i++)
if(strcmp(token,WORDS_KEY[i])==0) {key=i+1; break;}
return key;
}

void error() //错误调用函数
{
printf("There has some unlawful words!");
}

void print(WS *wd) //打印函数
{
printf("<%d,%s>",wd->syn,wd->value);
}
WS scaner() //扫描函数,主要算法
{
char token[20];
WS wd;
int c;
int i=0;
ch=fp.get();
getbc();
if(letter()) //是否为字母,是的话继续取字符,直到取的词不是字母或数字。调用reserve(char *token)判断是否为关键字。
{
while(letter()||digit())
{
token[i]=ch;
ch=fp.get();
i++;
}
token[i]='\0';
fp.seekg(-1,ios::cur); //退一个字符
c=reserve(token);
if(c!=10) { wd.syn=c;strcpy(wd.value,token); return wd;}
else { wd.syn=10;strcpy(wd.value,token);return wd;}
}
else if(digit()) //是否为数字,是的话继续取字符,直到取的词不是数字。
{
while(digit())
{
token[i]=ch;
ch=fp.get();
i++;
}
fp.seekg(-1,ios::cur);
token[i]='\0';
wd.syn=11;strcpy(wd.value,token);return wd;
}
else
{
switch(ch) //判断可识别字符
{
case '+': ch=fp.get();
if(ch=='+') {wd.syn=13;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;}
fp.seekg(-1,ios::cur);
wd.syn=25;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case '-': wd.syn=14;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case '*': wd.syn=15;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case '/': ch=fp.get();
if(ch=='*')
{
while(1)
{
ch=fp.get();
if(ch=='*')
{
ch=fp.get();
if(ch=='/')
break;
}
}
wd.syn=-1; return wd;
break;
}
fp.seekg(-1,ios::cur);wd.syn=16;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case '<': ch=fp.get();
if(ch=='='){ wd.syn=26;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;}
fp.seekg(-1,ios::cur);
wd.syn=18;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case ';': wd.syn=24;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case '(': wd.syn=20;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case ')': wd.syn=21;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case '{': wd.syn=22;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case '}': wd.syn=23;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case ',': wd.syn=19;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
case '=': wd.syn=17;wd.value[0]='-'; wd.value[1]='\0'; return wd; break;
default : wd.syn=-1; return wd;break;
}
}
}
int main()
{
WS wd;
ch=0;
if(!fp) cerr << "文件打开失败!" << endl;
while(ch!='#') //文件以"#"结束
{
wd=scaner();
if(wd.syn!=-1)
{ print(&wd);printf("\n");}
}
}

65,210

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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