注释转换器

让我们来实现一个注释转换器。它可以将拥有c风格(/* code */)或c++风格(// code)的注释的代码转换为c++风格。

刚开始看到这个题目是有点头晕的,因为各种注释的混合将使情况变得非常复杂,比如:

// 1.一般情况
/* 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++注释问题
// /*xxxxxxxxxxxxxxxxxxxx*/

这里只列举了几种情况,当然还有更多。所以想要单纯的通过if-else语句判断是很麻烦很麻烦的。由此,我们就想通过某种方法将这么多的复杂情况简化为几种状态,在这几种为数不多的状态里区分逻辑那就一目了然了。所以有限状态机来了。

有限状态机,(英语:Finite-state machine, FSM),又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型

由这个思路,我们可以画出如下模型(当然只是随便画画,并不严谨):

按注释风格将代码分为几种状态:

非注释代码称为无状态,c风格注释称为C转态,C++风格注释称为CPP状态,文件结束称为END状态。

箭头旁边的标注代表状态转换的条件,例如无状态指向C转态的箭头,意义为当在无状态下,遇到 '/*'则切换为C状态。

理清了这些逻辑,我们便可以很好的在各个转态之间切换了。下面贴上我写的代码(input.c作为测试代码源,output.c作为输出文件,都放在当前目录下):

头文件annotation_converter.h

#ifndef __ANNOTATION_CONCERTER__
#define __ANNOTATION_CONCERTER__

#include <stdio.h>
#include <stdlib.h>

#define INPUT_FILE_NAME "input.c"
#define OUTPUT_FILE_NAME "output.c"

typedef enum state
{
	NULL_STATE, 
	C_STATE,
	CPP_STATE,
	END_STATE
}STATE_TYPE;

void converter(void);
//核心转换函数
void converter_core(FILE *read, FILE *write);
//无状态处理
void converter_NULL(FILE *read, FILE *write, STATE_TYPE *pstate);
//C状态处理
void converter_c(FILE *read, FILE *write, STATE_TYPE *pstate);
//CPP状态处理
void converter_cpp(FILE *read, FILE *write, STATE_TYPE *pstate);



#endif

具体实现文件annotation_converter.c

#define _CRT_SECURE_NO_WARNINGS
#include "annotation_converter.h"
#include <assert.h>

void converter_NULL(FILE *read, FILE *write, STATE_TYPE *pstate)
{
	int first = 0, second = 0;

	while (*pstate == NULL_STATE)
	{
		first = fgetc(read);
		switch (first)
		{
		case '/':
		{
			second = fgetc(read);
			switch (second)
			{
			case '/':
				fputc(first, write);
				fputc(second, write);
				*pstate = CPP_STATE;
				break;
			case '*':
				fputc(first, write);
				fputc('/', write);
				*pstate = C_STATE;
				break;
			default:
				fputc(first, write);
				fputc(second, write);
				break;
			}
		}
			break;
		case EOF:
			*pstate = END_STATE;
			break;
		default:
			fputc(first, write);
			break;
		}
	}
}

void converter_c(FILE *read, FILE *write, STATE_TYPE *pstate)
{
	int first = 0, second = 0, third = 0;
	int flag = 0;

	while (C_STATE == *pstate)
	{	
		if (flag == 0)
			first = fgetc(read);
		switch (first)
		{
		case '*':
		{
			second = fgetc(read);
			if ('/' == second)
			{	
				third = fgetc(read);
				if (third != '\n')
					fputc('\n', write);
				ungetc(third, read);
				//flag = 0;
				*pstate = NULL_STATE;
			}
			else if ('*' == second)
			{
				fputc(first, write);
				first = second;
				flag = 1;
			}
			else
			{
				fputc(first, write);
				fputc(second, write);
			}
		}
			break;
		case '\n':
			fputc(first, write);
			fputc('/', write);
			fputc('/', write);
			break;
		case EOF:
			*pstate = END_STATE;
			break;
		default:
			fputc(first, write);
			break;
		}
	}
}

void converter_cpp(FILE *read, FILE *write, STATE_TYPE *pstate)
{
	int first = 0, second = 0;

	while (CPP_STATE == *pstate)
	{
		first = fgetc(read);
		switch (first)
		{
		case '\n':
			fputc(first, write);
			*pstate = NULL_STATE;
			break;
		case EOF:
			*pstate = END_STATE;
			break;
		default:
			fputc(first, write);
			break;
		}
	}
}

void converter_core(FILE *read, FILE *write)
{
	STATE_TYPE code_state = NULL_STATE;

	assert(read);
	assert(write);
	while (1)
	{
		switch (code_state)
		{
		case NULL_STATE:
			converter_NULL(read, write, &code_state);
			break;
		case C_STATE:
			converter_c(read, write, &code_state);
			break;
		case CPP_STATE:
			converter_cpp(read, write, &code_state);
			break;
		case END_STATE:
			return;
			break;
		default:
			break;
		}
	}
}

void converter()
{
	FILE *read = NULL;
	FILE *write = NULL;

	read = fopen(INPUT_FILE_NAME, "r");
	if (NULL == read)
	{
		perror("打开源文件错误\n");
		exit(0);
	}
	write = fopen(OUTPUT_FILE_NAME, "w");
	if (NULL == write)
	{
		perror("打开目标文件错误\n");
		fclose(read);
		exit(0);
	}

	converter_core(read, write);

	fclose(read);
	fclose(write);

}

测试文件 test.c

#include "annotation_converter.h"

int main()
{
	printf("annotaation_converter test\n");
	converter();

	return 0;
}

input.c

// 1.一般情况
/* 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++注释问题
// /*xxxxxxxxxxxxxxxxxxxx*/

output.c初始为空文件,执行程序后:

// 1.一般情况
// 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++注释问题
// /*xxxxxxxxxxxxxxxxxxxx*/

当然你也可以改用其它的input.c来测试。这里就不在试了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fireplusplus

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值