本文共 5945 字,大约阅读时间需要 19 分钟。
c语言中的注释方法为 /* ………*/
c++中的注释方法为 // 要将 input.txt里面的c语言注释全部转化为c++的注释,要考虑到各个不同的坑。例如:// 1.一般情况int num = 0;/* int i = 0; */// 2.换行问题/* int i = 0; */int j = 0;/* int i = 0; */int j = 0;// 3.匹配问题/*int i = 0;/*xxxxx*/// 4.多行注释问题/*int i=0;int j = 0;int k = 0;*/int k = 0;// 5.连续注释问题/**//**/// 6.连续的**/问题/***/// 7.C++注释问题// /*xxxxxxxxxxxx*/
要将上述所有的c语言注释全部转化为c++注释,上述中,每一种都是一个不同的情况,要是全部都用判断一下,没有总结是很难的。这时,我们就可以运用一种思想:状态机。就是将问题分成几种不同的状态,然后再几个状态之间来回转换。
例如上题中:一共可以分为四种状态:开始状态(无注释状态)、c语言注释状态、c++注释状态、结束状态。
这时候我们就要分析这几种状态之间对应的关系:如下图:#ifndef __COMMENT_CONVERT_H__ #define __COMMENT_CONVERT_H__ #include#include typedef enum State //定义一个枚举,里面是四种状态 { NUL_STATE, //无注释状态 C_STATE, //C语言注释状态 CPP_STATE, //C++注释状态 END_STATE //结束状态 }State; void DoNulState(FILE *pfRead, FILE *pfWrite, State *ps); //无注释状态操作 void DoCState(FILE *pfRead, FILE *pfWrite, State *ps); //C语言注释状态操作 void DoCppState(FILE *pfRead, FILE *pfWrite, State *ps); //C++注释状态操作 void CommentConvert(FILE *pfRead, FILE *pfWrite); //状态转换 #endif
#include "CommentConvert.h" void CommentConvert(FILE *pfRead, FILE *pfWrite) { enum State state = NUL_STATE; //开始为无注释状态 while (state != END_STATE) //如果不是结束状态,持续循环 { switch (state) { case NUL_STATE: //无注释状态 DoNulState(pfRead, pfWrite, &state); break; case C_STATE: //C语言注释状态 DoCState(pfRead, pfWrite, &state); break; case CPP_STATE: //C++注释状态 DoCppState(pfRead, pfWrite, &state); break; default: break; } } } void DoNulState(FILE *pfRead, FILE *pfWrite, State *ps) { int first = fgetc(pfRead); //记录第一个字符 switch(first) { case '/': //表示进入注释状态 { int second = fgetc(pfRead); //记录第二个字符 switch (second) { case '*': //代码为/* 即将进入C语言代码注释 { fputc('/', pfWrite); fputc('/', pfWrite); //将其转换为C++注释,并打印到output.txt中 *ps = C_STATE; //进入C语言代码注释状态 } break; case '/': //代码为// 即将进入C++代码注释状态 { fputc('/', pfWrite); fputc('/', pfWrite); // 将C++注释打印到output.txt中 *ps = CPP_STATE; //进入C++注释状态 } break; default: //不是C语言的注释,第一个字符只是一个字符'/' { fputc('/', pfWrite); //先将'/'打印 fputc(second, pfWrite); //再将第二个字符打印 } break; } } break; case EOF: //表示已经结束 { fputc(first, pfWrite); *ps = END_STATE; //进入结束状态 } break; default: { fputc(first, pfWrite); //表示第一个就是字符,将其打印 } break; } } void DoCState(FILE *pfRead, FILE *pfWrite, State *ps) { int first = fgetc(pfRead); //读取字符进行判断 switch (first) { case '*': //表示C语言注释可能会结束 { int second = fgetc(pfRead); //读取第二个字符 switch (second) { case '/': //遇见*/ 表示C语言注释结束 { int third = fgetc(pfRead); // 读取第三个字符,判断是否换行(上述中的第二种情况) if (third != '\n') //不是换行符 { fputc('\n', pfWrite); //要将其换行 ungetc(third, pfRead); //因为我们已经把该字符取出来了,接下来就不容易判断,所以还要讲该字符退回流中 } else { fputc(third, pfWrite); //如果是换行符,直接但因就可以 } *ps = NUL_STATE; //状态转换为无注释状态 } break; default: { fputc(first, pfWrite); //第二个字符不是'/',表示第一个 * 只是一个字符'*' ungetc(second, pfRead); //同上面一样,为了不影响下面的判断,要将该字符退回流中 } break; } } break; case '\n': //如果是换行符,就将其打印,但要加上两个/,因为C语言的注释是在每一行的开始 { fputc(first, pfWrite); fputc('/', pfWrite); fputc('/', pfWrite); } break; default : { fputc(first, pfWrite); //不是*,表示只是一个字符,将其打印 } break; } } void DoCppState(FILE *pfRead, FILE *pfWrite, State *ps) { int first = fgetc(pfRead); //读取第一个字符 switch (first) { case '\n': //如果是'\n',将其打印即可,并回到无注释状态 { fputc(first, pfWrite); *ps = NUL_STATE; } break; case EOF: // 表示结束,直接到结束状态 { fputc(first, pfWrite); *ps = END_STATE; } break; default: { fputc(first, pfWrite); //表示只是一个字符,将其打印 } break; } }
注:ungetc()表示把一个(或多个)字符退回到steam代表的文件流中
#define _CRT_SECURE_NO_WARNINGS 1 #include "CommentConvert.h" void test() { FILE *pfRead = NULL; FILE *pfWrite = NULL; pfRead = fopen("input.txt", "r"); if (pfRead == NULL) { perror("open file for read"); system("pause"); exit(EXIT_FAILURE); } pfWrite = fopen("output.txt", "w"); if (pfWrite == NULL) { perror("open file for write"); system("pause"); exit(EXIT_FAILURE); } CommentConvert(pfRead, pfWrite); fclose(pfRead); pfRead = NULL; fclose(pfWrite); pfWrite = NULL; } int main() { test(); system("pause"); return 0; }