【C++】注释转换详解 C++注释转换为标准C语言注释
2015-06-16 13:15
393 查看
在一个大型工程当中,由于代码人员的多样性,使得代码的注释风格不同。然而在发布版本中,注释风格应该保持一致,以便于其他人员在后期的使用和维护。 由此,产生了如下的需求:
实现对一个C/C++语言程序源文件中注释的转换功能(在这里 我们实现的是C++注释转换为标准C语言注释)
注释转化的要求:
其他注意事项:
具体分析:
在读取源文件的时候,可能遇到的情况有: C 风格注释(包含注释的嵌套),C++ 风格注释(包含注释的嵌套),字符中嵌套注释,无注释 ,结束等几种状态。
引入 “状态机”概念:
状态机简写为FSM(Finite State Machine),主要分为2大类:第一类,若输出只和状态有关而与输入无关,则称为Moore状态机;第二类,输出不仅和状态有关而且和输入有关系,则称为Mealy状态机。
状态机可归纳为4个要素,即现态、条件、动作、次态。这样的归纳,主要是出于对状态机的内在因果关系的考虑。"现态"和"条件"是因,"动作"和"次态"是果。详解如下:
①现态:是指当前所处的状态。
②条件:又称为"事件",当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。
③动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。
④次态:条件满足后要迁往的新状态。"次态"是相对于"现态"而言的,"次态"一旦被激活,就转变成新的"现态"了。
往往将抽象的状态转化为状态转移图:
从输入文件读取字符,判读并修改注释,生成新文件。(文件的操作 在这里不做概述)
代码实现:
主程序
注释转换程序:
测试用例(input文件):
输出文件(output):
实现对一个C/C++语言程序源文件中注释的转换功能(在这里 我们实现的是C++注释转换为标准C语言注释)
注释转化的要求:
其他注意事项:
具体分析:
在读取源文件的时候,可能遇到的情况有: C 风格注释(包含注释的嵌套),C++ 风格注释(包含注释的嵌套),字符中嵌套注释,无注释 ,结束等几种状态。
引入 “状态机”概念:
状态机简写为FSM(Finite State Machine),主要分为2大类:第一类,若输出只和状态有关而与输入无关,则称为Moore状态机;第二类,输出不仅和状态有关而且和输入有关系,则称为Mealy状态机。
状态机可归纳为4个要素,即现态、条件、动作、次态。这样的归纳,主要是出于对状态机的内在因果关系的考虑。"现态"和"条件"是因,"动作"和"次态"是果。详解如下:
①现态:是指当前所处的状态。
②条件:又称为"事件",当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。
③动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。
④次态:条件满足后要迁往的新状态。"次态"是相对于"现态"而言的,"次态"一旦被激活,就转变成新的"现态"了。
往往将抽象的状态转化为状态转移图:
从输入文件读取字符,判读并修改注释,生成新文件。(文件的操作 在这里不做概述)
代码实现:
主程序
#include<iostream> using namespace std; extern int CommentConvert(FILE *inputfile, FILE *outputfile); int main() { FILE *fpIn = NULL; //inputfile FILE *fpOut = NULL; //outputfile errno_t err; err = fopen_s(&fpIn, "input.c", "r"); if ((err = fopen_s(&fpIn, "input.c", "r")) != 0) { cout << "Open input file fail!" << endl; //return -1; } if ((err = fopen_s(&fpOut, "output.c", "w")) != 0) { cout << "Open output file fail!" << endl; //return -1; } CommentConvert(fpIn, fpOut); // fclose(fpIn); fclose(fpOut); return 0; }
注释转换程序:
#include<iostream> using namespace std; #define STACKSIZE 1024 #define UL unsigned long extern int CommentConvert(FILE *inputfile, FILE *outputfile); typedef enum { NO_COMMENT_STATE, C_COMMENT_STATE, CPP_COMMENT_STATE, STR_STATE, END_STATE }STATE_ENUM;//状态列表 typedef struct { FILE *inputfile; FILE *outputfile; STATE_ENUM ulstate; }STATE_MACHINE; //状态机 // STATE_MACHINE g_state = { 0 }; /////////////////////////////////////////////////// void EventPro(char ch);//事件驱动 void EventProAtNo(char ch); void EventProAtC(char ch); void EventProAtCpp(char ch); void EventProAtStr(char ch); //////////////////////////////////////////////////// int CommentConvert(FILE *inputfile, FILE *outputfile) { if (inputfile == NULL || outputfile == NULL) { cout << "input argument Invalid!" << endl; return -1; } g_state.inputfile = inputfile; g_state.outputfile = outputfile; g_state.ulstate = NO_COMMENT_STATE; //初始状态为无注释状态 char ch; while (g_state.ulstate != END_STATE) { ch = fgetc(g_state.inputfile); // EventPro(ch); } return 0; } void EventPro(char ch) //事件驱动模型 { switch (g_state.ulstate) //不同的事件状态使用不同的状态函数 { case NO_COMMENT_STATE: EventProAtNo(ch); break; case C_COMMENT_STATE: EventProAtC(ch); break; case CPP_COMMENT_STATE: EventProAtCpp(ch); break; case STR_STATE: EventProAtStr(ch); break; case END_STATE: break; } } void EventProAtNo(char ch) { char nextch; switch (ch) { case '/': // // /* nextch = fgetc(g_state.inputfile); if (nextch == '/') // C++ { fputc('/', g_state.outputfile); fputc('*', g_state.outputfile); //将CPP的//转化为/* g_state.ulstate = CPP_COMMENT_STATE;//转换为CPP状态 } else if (nextch == '*') //C { fputc(ch, g_state.outputfile); fputc(nextch, g_state.outputfile); g_state.ulstate = C_COMMENT_STATE;//转换为C状态 } else { } break; case EOF: g_state.ulstate = END_STATE; break; case '"': fputc('"', g_state.outputfile); g_state.ulstate = STR_STATE; break; default: fputc(ch, g_state.outputfile); break; } } void EventProAtC(char ch) { char nextch; switch (ch) { case '*': nextch = fgetc(g_state.inputfile); if (nextch == '/') { fputc(ch, g_state.outputfile); fputc(nextch, g_state.outputfile); g_state.ulstate = NO_COMMENT_STATE; } break; case '/': nextch = fgetc(g_state.inputfile); if (nextch == '/') { fputc(' ', g_state.outputfile); fputc(' ', g_state.outputfile);//嵌套注释用两个空格代替 } break; default: fputc(ch, g_state.outputfile); break; } } /// <summary> /// Events the pro at CPP. /// </summary> /// <param name="ch">The ch.</param> void EventProAtCpp(char ch) { //123 /*123 char nextch; switch (ch) { case '\n': //处理多行 fputc('*', g_state.outputfile); fputc('/', g_state.outputfile); fputc('\n', g_state.outputfile); g_state.ulstate = NO_COMMENT_STATE; break; case EOF: fputc('*', g_state.outputfile); fputc('/', g_state.outputfile); g_state.ulstate = END_STATE; break; case '/': nextch = fgetc(g_state.inputfile); if (nextch == '/') // (嵌套//) { fputc(' ', g_state.outputfile); fputc(' ', g_state.outputfile); } else if (nextch == '*') // (嵌套 /*) { fputc(' ', g_state.outputfile); fputc(' ', g_state.outputfile); } else { fputc(ch, g_state.outputfile); } break; case '*': nextch = fgetc(g_state.inputfile); if (nextch == '/') // 嵌套// { fputc(' ', g_state.outputfile); fputc(' ', g_state.outputfile); } else { fputc(ch, g_state.outputfile); } break; case'"': g_state.ulstate = STR_STATE; default: fputc(ch, g_state.outputfile); break; } } void EventProAtStr(char ch) { char nextch; switch (ch) { case '\0': nextch = fgetc(g_state.inputfile); if (nextch == '"') //读取到 \0 和 " 说明字符串结束 g_state.ulstate = NO_COMMENT_STATE; //状态切换 break; case EOF: g_state.ulstate = END_STATE; break; default: fputc(ch, g_state.outputfile); break; } }
测试用例(input文件):
//每个区由若干个内存块组成 //每个区由若干个内存块组成,//每个块是4096个字节 //int i = 0;*/ //*//*int i = 0; // /**/int i = 0; /* int i = 0; *//* */ /* int i = 0; //*/int j = 0; /* //每个区由若干个内存块组成,每个块是4096个字节 //每个块的第0个整数指向下个区 //所以是单链表结构 //所以每个区只有4092个字节存放真正的数据 */ /* int i = 0;*//*int j = 0; */ /* *//* */int i = 0; //////////////////////////////////////////////////////////////////// 5 "abcdefghijklmn~~~~!!!!!!!!" //dsgf sdfg " fs sdfsg // /* */ " " fs sdfsg // /* */ "
输出文件(output):
/*每个区由若干个内存块组成*/ /*每个区由若干个内存块组成, 每个块是4096个字节*/ /*int i = 0; */ /* int i = 0;*/ /* int i = 0;*/ /* int i = 0; *//* */ /* int i = 0; */int j = 0; /* 每个区由若干个内存块组成,每个块是4096个字节 每个块的第0个整数指向下个区 所以是单链表结构 所以每个区只有4092个字节存放真正的数据 */ /* int i = 0;*//*int j = 0; */ /* *//* */int i = 0; /* 5*/ "abcdefghijklmn~~~~!!!!!!!!" //dsgf sdfg " fs sdfsg // /* */ " " fs sdfsg // /* */ "
相关文章推荐
- [C/CPP系列知识] 那些程序C语言可以编译通过但C++无法编译成功 Write a C program that won’t compile in C++
- C++课后习题作业
- C++ mkdir() 头文件
- 北京c++技术交流 235760268
- C\C++代码优化的27个建议
- 【整理】--C++变量概述
- C++中代理类和句柄类
- C++【多重继承和虚继承】
- 错误的结果 -1073741819 从"C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\mt.exe"返回
- C++11变长模板解析(深入理解C++11)
- 学习笔记 C++ const放在函数体前和函数参数列表之后的作用
- C++【浅谈虚析构函数】
- C++对二进制文件的读写操作
- 注释转换(C++到C)
- C++语法总结,语法查询
- C++vector
- C++静态库与动态库
- 《C++语言基础》实践参考——max带来的冲突
- 《C++语言基础》实践参考——有些数的阶乘不算了
- 《C++语言基础》实践参考——平方根中的异常