注释转换-小程序
程序员文章站
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;
}
}
#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*/