注释转换-小程序

编写代码时会有多种注释方式,但有的编辑环境不识别其他的注释方式,因此做个小项目来实现将注释方式统一的改为一种。本次注释转换这个小项目就是将所有的C注释全部转换为C++注释。


要实现这个转换就要先理清实际过程中代码都有哪几种状态!所以先来列一个状态转换机来梳理一下什么情况是什么状态。

简单考虑有以下几种状态:

1、无状态:代码的正文部分

2、C状态:注释方式为C注释

3、C++状态:注释方式为C++注释

4、END:结束状态

为了更加清楚直观的了解他们之间的转换关系,用图示的方法来说明一下


首先我们要打开input.c文件,对这个文件内部的文件进行读取,然后处理,否则直接提示用户有错误。 接下来,我们还要打开output.c文件,对处理以后的代码进行写入。

先来说一下转换机制:先创建一个状态机,在读取到文件时将初始状态先设为NULL_STATE,然后通过fputc函数

从文件中按一个字符一个字符的方式来读取,当读到'/*'时,说明接下来读到的是C_STATE状态,然后将状态机的

状态改为C_STATE状态,进入C状态后,接下来就是要判断是否读到'*/',如果读到就将状态机设置为 

NULL_STATE状态。当然在进去C状态后还要考虑其他很多情况,具体在代码中来看。当读到'//'时,则进入

CPP_STATE状态,这时将状态机设置为CPP_STATE状态,CPP注释是按照行来注释的,所以判断CPP状态结束

的标志自然就是'\n'了。在了解了状态机的转换机制之后,接下来就在代码中具体来实现


transform.h

#define _CRT_SECURE_NO_WARNINGS 1

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

#ifndef _TRANSFORM_H_
#define _TRANSFORM_H_

#define _PATHREAD_ "input.c"
#define _PATHWRITE_ "output.c"

typedef enum STATE
{
	NUL_STATE, //空状态
	C_STATE,	//C状态
	CPP_STATE,	//C++状态
	END		//结束状态
}STATE;


void transform(FILE* _read, FILE* _write);	//注释状态
void DoCstate(FILE* _read, FILE* _write, STATE *ps);//C状态,结束C状态时要注意注释状态,所以加上结构体指针
void DoCPPstate(FILE* _read, FILE* _write, STATE *ps);//C++状态
void DoNULstate(FILE* _read, FILE* _write, STATE *ps);//结束




#endif //_TRANSFORM_H_

transform.c

#include "transform.h"

void transform(FILE* _read, FILE* _write)
{
	STATE state = NUL_STATE;	//初始状态设为无状态
	while(state != END)
	{
		switch(state)
		{
		case NUL_STATE:
			DoNULstate(_read, _write, &state);//因为要改变地址的状态,所以穿过去的是状态的地址
			break;
		case C_STATE:
			DoCstate(_read, _write, &state);
			break;
		case CPP_STATE:
			DoCPPstate(_read, _write, &state);
			break;
		default:
			break;
		}
	}
}

void DoNULstate(FILE *_read, FILE *_write, STATE *ps)
{
	int first = 0;
	int second = 0;
	int third = 0;
	first = fgetc(_read);
	switch(first)
	{
	case '/':
		second = fgetc(_read);
		switch (second)
		{
		case '*':
			{
				fputc('/',_write);//当读到/*时相当于是C状态,状态改变为C状态
				fputc('/',_write);//然后把C注释的标志/*变为C++注释的标志//
				*ps = C_STATE;
			}
			break;
		case '/':
			{
				fputc(first,_write);//遇到//相当于C++状态,不用转换直接把读到的标志写进去
				fputc(second,_write);
				*ps = CPP_STATE;//状态变为C++状态
			}
			break;
		default:
			fputc(first,_write);
			fputc(second,_write);
			break;
		}
		break;
	case EOF://遇到EOF直接把状态变为结束
		fputc(first, _write);
		*ps = END;
		break;
	default:
		fputc(first, _write);//没有读到注释的标注就直接把读到的写进去
		break;
	}
}

void DoCstate(FILE *_read, FILE *_write, STATE *ps)
{
	int first = 0;
	int second = 0;
	int third = 0;
	first = fgetc(_read);
	switch(first)
	{
	case '*':
		{
			second = fgetc(_read);
			switch (second)
			{
			case '/'://进入C状态后如果读到*/就说明结束了C状态的注释
				third = fgetc(_read);//这里只是考虑避免注释到了正文
				if(third == '\n')
				{
					fputc(third, _write);
				}
				else
				{
					ungetc(third, _read);//读到非\0时就是*/后面有正文内容,所以回退一下
					fputc('\n', _write);
				}
				*ps = NUL_STATE;
				break;
			case '*':
				fputc(first, _write);
				ungetc(second, _read);//遇到两个*,则第一个是正文的*
				break;
			default:
				fputc(first, _write);
				break;
			}
		}
		break;
	case '\n'://C注释换行问题
		fputc(first,_write);
		fputc('/',_write);
		fputc('/',_write);
		break;
	case EOF:
		fputc(first, _write);
		*ps = END;
	default:
		fputc(first,_write);
		break;
	}
}

void DoCPPstate(FILE* _read, FILE* _write, STATE *ps)
{
	int first = 0;
	int second = 0;
	first = fgetc(_read);
	switch(first)
	{
	case '\n'://C++状态是按行注释,当一行结束时就把状态变为无状态
		{
			fputc('\n',_write);
			*ps = NUL_STATE;
		}
		break;
	case EOF:
		fputc(first, _write);
		*ps = END;
		break;
	default:
		fputc(first,_write);
		break;
	}
}


test.c

#include "transform.h"

int main()
{
	FILE* fdread;
	FILE* fdwrite;
	fdread = fopen(_PATHREAD_,"r");
	if(fdread == NULL)
	{
		perror("open file for read!\n");
		exit(EXIT_FAILURE);
	}
	fdwrite = fopen(_PATHWRITE_,"w");
	if(fdwrite == NULL)
	{
		fclose(fdread);
		perror("open file for write!\n");
		exit(EXIT_FAILURE);
	}
	transform(fdread,fdwrite);

	fclose(fdread);
	fclose(fdwrite);
	system("pause");
	return 0;
}


为了测试项目的效果,采用以下七种方式来测试来判断是否正确


input.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*/


输出的结果为:

output.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;/*xxxx

// 4.多行注释问题
//
//int i=0;
//int j = 0;
//int k = 0;
//
int k = 0;

// 5.连续注释问题
//
//

// 6.连续的**/问题
//*

// 7.C++注释问题
// /*xxxxxxxxxxxx*/




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值