您的位置:首页 > 编程语言 > C语言/C++

【C++】注释转换详解 C++注释转换为标准C语言注释

2015-06-16 13:15 393 查看
在一个大型工程当中,由于代码人员的多样性,使得代码的注释风格不同。然而在发布版本中,注释风格应该保持一致,以便于其他人员在后期的使用和维护。 由此,产生了如下的需求:

实现对一个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 //   /*  */  "
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: