欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

注释转换-小程序

程序员文章站 2022-07-14 16:45:34
...

编写代码时会有多种注释方式,但有的编辑环境不识别其他的注释方式,因此做个小项目来实现将注释方式统一的改为一种。本次注释转换这个小项目就是将所有的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*/