最近在编译原理的学习中的实验。 对C或C++等高级程序设计语言编写的源程序中的//注释和/…/注释进行删除,保留删除后的源程序。 要求以文件形式进行保存。
算法分析 注释情况比较复杂,备注标识有两情况://与/* 且代码内会含有/与*,甚至有转义字符以及字符串内含有备注标识 对此我选择使用状态机进行相应的算法设计:
00)设正常状态为0,并初始为正常状态 向下遍历所有状态,全部成立或检查完毕,返回至此检查下一状态 01)状态0中遇到/,说明可能会遇到注释,则进入状态1 ex:int a = b;/ 02)状态1中遇到*,说明进入多行注释部分,则进入状态2 ex:int a= b; /* 03)状态1中遇到/,说明进入单行注释部分,则进入状态4 ex:int a = b; // 04)状态1中没有遇到或/,说明/是路径符号或除号,则恢复状态0 ex:<secure/_stdio.h> or 5/3 05)状态2中遇到,说明多行注释可能要结束,则进入状态3 ex:int a = b; /heh 06)状态2中不是遇到*,说明多行注释还在继续,则维持状态2 ex:int a = b; /hehe 07)状态3中遇到/,说明多行注释要结束,则恢复状态0 ex:int a = b; /hehe/ 08)状态3中不是遇到/,说明多行注释只是遇到,还要继续,则恢复状态2 ex:int a = b; /heheh 09)状态4中遇到\,说明可能进入折行注释部分,则进入状态9 ex:int a = b; //hehe 10)状态9中遇到\,说明可能进入折行注释部分,则维护状态9 ex:int a = b; //hehe\ 11)状态9中遇到其它字符,则说明进入了折行注释部分,则恢复状态4 ex:int a = b; // hehe\a or hehe<enter> 12)状态4中遇到回车符\n,说明单行注释结束,则恢复状态0 ex:int a = b; //hehe 13)状态0中遇到’,说明进入字符常量中,则进入状态5 ex:char a = ’ 14)状态5中遇到\,说明遇到转义字符,则进入状态6 ex:char a = ’ 15)状态6中遇到任何字符,都恢复状态5 ex:char a = ‘\n 还有如’\t’, ‘’’, ‘\’ 等 主要是防止’’’,误以为结束 16)状态5中遇到’,说明字符常量结束,则进入状态0 ex:char a = ‘\n’ 17)状态0中遇到",说明进入字符串常量中,则进入状态7 ex:char s[] = " 18)状态7中遇到\,说明遇到转义字符,则进入状态8 ex:char s[] = " 19)状态8中遇到任何字符,都恢复状态7 ex:char s[] = “\n 主要是防止”",误以为结束 20)状态7中遇到"字符,说明字符串常量结束,则恢复状态0 Ex:char s[] = "“hehe”
只需要在某特定状态输出字符即可(0、5、6、7、8) if ((state == 0 && c != ‘/’) || state == 5 || state == 6 || state == 7 || state == 8){ 输出动作; }
读存文件部分
ifstream ifile; //建立文件流对象 ofstream ofile; ifile.open(“s.cpp”); //待处理文件 ofile.open(“d.cpp”); //无备注文件 if (ifile.fail() || ofile.fail()) { //测试打开操作是否成功 cerr << “open file fail\n”; return EXIT_FAILURE; }
源代码
#include<iostream> #include<fstream> #include<iomanip> #include<cstdlib> using namespace std; int main() { ifstream ifile; //建立文件流对象 ofstream ofile; ifile.open("s.cpp"); ofile.open("d.cpp"); if (ifile.fail() || ofile.fail()) { //测试打开操作是否成功 cerr << "open file fail\n"; return EXIT_FAILURE; } int state; state = 0; char c; c = ifile.get(); //进行读写操作 while (!ifile.eof()) { if (state == 0 && c == '/') // ex. [/] state = 1; else if (state == 1 && c == '*') // ex. [/*] state = 2; else if (state == 1 && c == '/') // ex. [//] state = 4; else if (state == 1) { // ex. [<secure/_stdio.h> or 5/3] putchar('/'); state = 0; } else if (state == 2 && c == '*') // ex. [/*he*] state = 3; else if (state == 2) // ex. [/*heh] state = 2; else if (state == 3 && c == '/') // ex. [/*heh*/] state = 0; else if (state == 3) // ex. [/*heh*e] state = 2; else if (state == 4 && c == '\\') // ex. [//hehe\] state = 9; else if (state == 9 && c == '\\') // ex. [//hehe\\\\\] state = 9; else if (state == 9) // ex. [//hehe\<enter> or //hehe\a] state = 4; else if (state == 4 && c == '\n') // ex. [//hehe<enter>] state = 0; else if (state == 0 && c == '\'') // ex. ['] state = 5; else if (state == 5 && c == '\\') // ex. ['\] state = 6; else if (state == 6) // ex. ['\n or '\' or '\t etc.] state = 5; else if (state == 5 && c == '\'') // ex. ['\n' or '\'' or '\t' ect.] state = 0; else if (state == 0 && c == '\"') // ex. ["] state = 7; else if (state == 7 && c == '\\') // ex. ["\] state = 8; else if (state == 8) // ex. ["\n or "\" or "\t ect.] state = 7; else if (state == 7 && c == '\"') // ex. ["\n" or "\"" or "\t" ect.] state = 0; //debug("c = %c, state = %d\n", c, state); if ((state == 0 && c != '/') || state == 5 || state == 6 || state == 7 || state == 8) ofile.put(c); c = ifile.get(); //从输入文件对象流中读取一个字符 } ifile.close(); //关闭文件 ofile.close(); return 0; }文章用于记录学习与知识交流,欢迎评论讨论与批评。 参考文章:https://www.cnblogs.com/zhanghaiba/p/3569928.html