每个程序员的代码注释风格不同,为统一代码注释风格,有时需要将c++注释转化为c语言注释或者反之,人工修改速度太慢,且容易出错,要是有一个专门负责注释代码转化的程序,必定事半功倍!!
题目要求:
注释转化要求如下:
注释的嵌套情形很多,这里只是举例,你需要遵照C/C++语言的注释规则来编写代码,我不会仅测试这里的例子。
1、单行注释或没有嵌套,注释行直接转换,如:
①//123 /* 123 */
②/* 123 */ /* 123 */ 不变
③/*123
*/ 保持原样
2、有嵌套的注释(一个注释中还有嵌套其他注释符号//,/* */)嵌套中多余的每个注释符号用两个空格代替。
如单行:
① //123 /*456 */ /*123 456*/
②//123//456 /*123 456*/
③//123*//*456 /*123 456*/
如跨行
/*…….. /*……..
//……… ……….
// …….. ……….
*/ */
注意事项:
1、除以下两种情况的修改,源文件转换后不能有任何其它的修改:
①多余的注释符用空格代替
②//在注释开始替换为/* ,行尾增加*/
2、下面的3种情形无需转换① /* 123 */ /* 456 */
②/* 123 */ /* 456
*/
③/* 123
*/ /* 456
*/
3、不需要考虑输入文件中不符合语法规则的注释
代码如下:
CommentConvert.cpp
#include
using namespace std;
#define UL unsigned long
extern int CommentConvert(FILE *inputfile, FILE *outputfile);//引入外部函数
/*枚举:各种状态*/
typedef enum
{
NO_COMMENT_STATE, //无注释状态
C_COMMENT_STATE, //c语言注释状态
CPP_COMMENT_STATE,//c++注释状态
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<
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;
}
}
/*初始状态开始:可能转化:c注释,c++注释,终态,字符串状态*/
void EventProAtNo(char ch)
{
char nextch;
switch(ch)
{
case '/': // // /*
nextch = fgetc(g_state.inputfile);
if(nextch == '/') // C++注释开始,按c注释打印
{
fputc('/',g_state.outputfile);
fputc('*',g_state.outputfile);
g_state.ulstate = CPP_COMMENT_STATE;
}
else if(nextch == '*') //C注释开始,原样打印
{
fputc(ch,g_state.outputfile);
fputc(nextch,g_state.outputfile);
g_state.ulstate = C_COMMENT_STATE;
}
else
{}
break;
case '"'://字符串状态
fputc(ch,g_state.outputfile);
g_state.ulstate = STR_STATE;
break;
case EOF://终态
g_state.ulstate = END_STATE;
break;
default:
fputc(ch,g_state.outputfile);
break;
}
}
/*c注释状态:可能遇到:c注释结束-->终态 c注释(空格代替),c++注释(空格代替),字符串状态(中的注释不改变)*/
void EventProAtC(char ch)
{
char nextch;
switch(ch)
{
case '*':
nextch = fgetc(g_state.inputfile);
if(nextch == '/')//c语言注释结束
{
fputc(ch,g_state.outputfile);
fputc(nextch,g_state.outputfile);
g_state.ulstate = NO_COMMENT_STATE;
}
else
{
fputc(ch,g_state.outputfile); //只有一个*号,将其打印
fseek(g_state.inputfile,-1,1);//因为求nextch时调用fgetc,指针后移了一位,所以得将指针前移一位,否则会跳过一个字符
}
break;
case '/':
nextch = fgetc(g_state.inputfile);
if(nextch == '/' || nextch == '*')//掺杂c++或者c语言注释,用两个空格代替
{
fputc(' ',g_state.outputfile);
fputc(' ',g_state.outputfile);
}
else
{
fputc(ch,g_state.outputfile); //只有一个/号,将其直接打印
fseek(g_state.inputfile,-1,1);//因为求nextch时调用fgetc,指针后移了一位,所以得将指针前移一位,否则会跳过一个字符
}
break;
case '"'://字符串状态
fputc(ch,g_state.outputfile);
g_state.ulstate = STR_STATE;
break;
default:
fputc(ch,g_state.outputfile);
break;
}
}
//c++注释状态中可能包含:c注释(空格代替),c++注释(空格代替),字符串状态(中的注释不改变)
void EventProAtCpp(char ch)
{
//123 /*123
char nextch;
switch(ch)
{
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
{
fputc(ch,g_state.outputfile);
fseek(g_state.inputfile,-1,1);
}
break;
case '/':
nextch = fgetc(g_state.inputfile);
if(nextch == '*')//掺杂c语言注释,用两个空格代替
{
fputc(' ',g_state.outputfile);
fputc(' ',g_state.outputfile);
}
else if(nextch == '/')//掺杂c++注释,用两个空格代替
{
fputc(' ',g_state.outputfile);
fputc(' ',g_state.outputfile);
}
else
{
fputc(ch,g_state.outputfile);
fseek(g_state.inputfile,-1,1);
}
break;
case '"'://字符串状态
fputc(ch,g_state.outputfile);
g_state.ulstate = STR_STATE;
break;
default:
fputc(ch,g_state.outputfile);
break;
}
}
/*字符串状态:c注释(原样输出)c++注释(原样输出),终态*/
void EventProAtStr(char ch)
{
char nextch;
switch(ch)
{
case '\0':
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 EOF:
g_state.ulstate = END_STATE;
default:
fputc(ch,g_state.outputfile);
break;
}
}main.cpp
#include
using namespace std;
extern int CommentConvert(FILE *inputfile, FILE *outputfile);
int main()
{
FILE *fpIn = NULL; //inputfile
FILE *fpOut = NULL; //outputfile
fpIn = fopen("input.c","r");
if(NULL == fpIn)
{
cout<
return -1;
}
fpOut = fopen("output.c","w");
if(NULL == fpOut)
{
cout<
return -1;
}
CommentConvert(fpIn,fpOut); //
fclose(fpIn);
fclose(fpOut);
return 0;
}
测试用例如下
输入input.c:
//abc**def
//每个区由若干个内存块组成
//每个区由若干个内存块组成,//每个块是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
char *s = "abcdefghijklmn//~~/*~~*/!!!!!!!!";
output.c:
/*abc**def*/
/*每个区由若干个内存块组成*/
/*每个区由若干个内存块组成*/
/*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*/
char *s = "abcdefghijklmn//~~/*~~*/!!!!!!!!";
有关状态机的概念
点击此处点击打开链接