#include<stdio.h> #include<malloc.h> #define READ(ch) ch=getc(fp) /*宏:READ(ch)*/ char ch; /*声明为全局变量*/ int right=0; FILE *fp; struct struCH { char ch; struct struCH *next; }struCH,*temp,*head,*shift; /*head指向字符线性链表的头结点*/ /*shift指向动态建成的结点(游标)*/ void main(int argc,char *argv[]) { void E (); /* P(E) */ void E1(); /* P(E')*/ void T (); /* P(T) */ void T1(); /* P(T')*/ void F (); /* P(F) */ int errnum=0,k=0,m=0,countchar=0,rownum; int charerr=0; /*开关控制量*/ /************************以只读方式打开文件*********************/ if((fp=fopen(argv[1],"r"))==NULL) { printf("\n\tCan not open file %s,or not exist it!\n",argv[1]); exit(0); /*文件不存在or打不开时,正常退出程序*/ } else printf("\n\tSuccess open file: %s\n",argv[1]); /*成功打开文件*/ /******************遍历整个文件检测是否有非法字符********************/ /*如果用while(!feof(fp))语言,将会多出一个字符 *所以这里采用以下方法遍历整个文件检测其否有非法字符 */ /*[1]计算文件中字符数量*/ while(!feof(fp)) { READ(ch); /*这里读取字符只是让文件指针往前移*/ countchar++; /*统计文件中的字符数(包括换行符及文件结束符)*/ } rewind(fp); /*将fp文件指针重新指向文件头处,以备后面对文件的操作*/ if(countchar==0) { /*空文件*/ printf("\t%s is a blank file!\n",argv[1]); exit(0); /*正常退出本程序*/ } /*[2]开始遍历文件*/ while(k<(countchar-1)) { /*加换行符后countchar仍多了一个,不知为何*/ ch=getc(fp); if(!(ch=='('||ch==')'||ch=='i'||ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='#'||ch=='\n')) { charerr=1;errnum++; /*charerror出错标记,errnum统计出错个数*/ } k++; } rewind(fp); /*将fp文件指针重新指向文件头处,以备后面的建链表操作*/ if(charerr==1) { /*文件中有非法字符*/ printf("\n\t%d Unindentify characters in file %s \n",errnum,argv[1]); exit(0); /*正常退出本程序*/ } /*******************非空且无非法字符,则进行识别操作*****************/ for(rownum=1;m<(countchar-1);rownum++) { /*识别所有行,rownum记录行号*/ /*初始变量及堆栈和*/ right=1; /*初始存放待识别的表达式的线性链表头*/ shift=malloc(sizeof(struCH)); shift->next=NULL; head=shift; /*读取一行形成线性链表*/ READ(ch); putchar(ch); m++; while(ch!='\n'&&m<(countchar)) { /*行末or到文件尾。最后会读取文件结束符*/ /*读取ch,读取存入结点,这样每行便形成一个线性链表*/ temp=malloc(sizeof(struCH)); temp->ch=ch; temp->next=NULL; shift->next=temp; shift=shift->next; READ(ch); if(m!=(countchar-1)) putchar(ch); /*不输出最后一次读取的文件结束符*/ m++; } head=head->next; /*消去第一个空头结点,并使head指向非空线性链表头*/ shift=head; /*shift指向头结点,以便后面识别操作*/ putchar('\n'); E(); /*开始识别一行*/ if(shift->ch=='#'&&right) /*正确提示:[文件名] Line [行号]:right expression!*/ printf("%s Line %d:\t right expression!\n",argv[1],rownum); else /*错误提示:[文件名] Line [行号]:error expression!*/ printf("%s Line %d:\t error expression!\n",argv[1],rownum); putchar('\n'); }/*end for*/ printf("Completed!\n"); fclose(fp); /*关闭文件*/ exit(0); /*正常结束程序*/ } /*以下函数分别对应于子模块程序*/ void E() { T(); E1(); } void E1() { if(shift->ch=='+'||shift->ch=='-') { shift=shift->next; T(); E1(); } else { if(shift->ch=='#'||shift->ch==')') return; else right=0; } } void T(void) { F(); T1(); } void T1(void) { if(shift->ch=='*'||shift->ch=='/') { shift=shift->next; F(); T1(); } else { if(shift->ch!='#'&&shift->ch!=')'&&shift->ch!='+'&&shift->ch!='-') right=0; /*如果不是'#'or')'or'+'or'+'or'-'则出错*/ } } void F(void) { if(shift->ch=='i') shift=shift->next; else { if(shift->ch=='(') { shift=shift->next; E(); if(shift->ch==')') shift=shift->next; else right=0; } else right=0; } }