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

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

实现对一个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 '"':
		g_state.ulstate = STR_STATE;
	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;
	}
}
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 //   /*  */  "
时间: 2024-10-12 14:58:57

【C++】注释转换详解 C++注释转换为标准C语言注释的相关文章

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

一.具体要求: 1:C风格的注释/* */注释转换为标准C++风格//注释 2://   风格的注释保持原样 3:所有的转换需要符合语法规则 4:注释转换需要支持注释嵌套 二.转换要求: 注释的嵌套情形很多,这里只是举例,你需要遵照C/C++语言的注释规则来编写代码,我不会仅测试这里的例子.                                                          三.注意事项: 1.除以下两种情况的修改,源文件转换后不能有任何其它的修改: a.多余的注释

注释转换??——C++注释转换为标准C语言注释

编写注释转化程序,实现对一个C/C++语言程序源文件中注释的转换功能 1.C++风格的注释//注释转换为标准C分风格/* */注释 2./* */风格的注释保持原样 3.所有的转换需要符合语法规则 4.注释转换需要支持注释嵌套 注释转化要求: 注释的嵌套情形很多,这里只是举例,你需要遵照C/C++语言的注释规则来编写代码,我不会仅测试这里的例子. 1.单行注释或没有嵌套,注释行直接转换,如: ①//123 /* 123 */ ②/* 123 / / 123 */ 不变 ③/*123 */ 保持原

Java 注释规范详解

原文同步至:http://www.waylau.com/java-comments-conventions/ 在 Java 的编写过程中我们需要对一些程序进行注释,除了自己方便阅读,更为别人更好理解自己的程序,所以我们需要进行一些注释,可以是编程思路或者是程序的作用,总而言之就是方便自己他人更好的阅读. 注释类型 Java 有两类注释: implementation comments(实现注释)和 documentation comments(文档注释). 实现注释常见于 C++,使用 /*..

CvMat、Mat、IplImage之间的转换详解及实例

见原博客:http://blog.sina.com.cn/s/blog_74a459380101obhm.html OpenCV学习之CvMat的用法详解及实例 CvMat是OpenCV比较基础的函数.初学者应该掌握并熟练应用.但是我认为计算机专业学习的方法是,不断的总结并且提炼,同时还要做大量的实践,如编码,才能记忆深刻,体会深刻,从而引导自己想更高层次迈进. 1.初始化矩阵: 方式一.逐点赋值式: CvMat* mat = cvCreateMat( 2, 2, CV_64FC1 ); cvZ

ASA nat转换详解与扩展ACL详解

AR1区 telnet AR2 经过ASA1 转换流量配置如下:ASA配置:ASA Version 8.4(2)!hostname ciscoasaenable password 8Ry2YjIyt7RRXU24 encryptedpasswd 2KFQnbNIdI.2KYOU encryptednames!interface GigabitEthernet0nameif insidesecurity-level 100ip address 192.168.10.254 255.255.255.

图文详解AO打印(标准模式)

一.概述 AO打印是英文Active-Online Print的简称,也称主动在线打印.打印前支持AO通讯协议的AO打印机(购买地址>>)首先通过普通网络与C-Lodop服务保持在线链接,网页程序利用JavaScript语句向打印机输出复杂内容. 相比于传统网络打印,打印机由被动链接变为主动链接,这种部署的优势很明显,既可以外网异地打印,也可以内外网本地打印,对打印两端的网络位置无要求,从而轻松实现广域网远程打印,手机.平板打印问题也一举搞定.鉴于当前宽带普及,加之云服务器租金越来越便宜,这都

c++ cout&lt;&lt; cin&gt;&gt; 注释符 详解

std::cout是在#include<iostream>库中的ostream类型中的对象 std::表示命名空间,标准库定义的所有名字都在命名空间std中 std::cout是在#include<iostream>库中的istream类型中的对象 std::cout<<a<<std::endl; 上条语句中<<是输入运算符,就是将大头的那边的量弄进箭头所指的对象中,并返回运算之后的箭头所指的对象 std::endl是一个操纵符,作用是结束当前行

使用Eclipse设置Java注释模板详解

设置注释模板的入口: Window->Preference->Java->Code Style->Code Template 然后展开Comments节点就是所有需设置注释的元素啦.现就每一个元素逐一介绍: 文件(Files)注释标签: /** * @Title: ${file_name} * @Package ${package_name} * @Description: ${todo}(用一句话描述该文件做什么) * @author A18ccms A18ccms_gmail_

phpDocumentor 注释语法详解

PHPDocumentor是强大的代码注释生成器,本文对各个参数进行了简单地的总结: @abstract-------------使用@abstract标记来声明一个方法,类变量或类必须重新定义子类中是有效的. @abstract -------------使用@abstract标记来声明一个方法,类变量或类是抽象的.一个类中,只要有一个抽象方法,这个类必须被声明为抽象类.抽象方法在子类中必须被重写.抽象类在被继承后,其中的抽象方法不能被重写. @access-------------访问权限p