最近做了一个注释转换的项目,将C语言注释转化为C++格式。
在这个项目中,我用到了有限状态机的思想。有限状态机,简称为状态机(finite-state machine),是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。
我先来介绍一下状态机。状态机简写为FSM(Finite State Machine),主要分为2大类:第一类,若输出只和状态有关而与输入无关,则称为Moore状态机;第二类,输出不仅和状态有关而且和输入有关系,则称为Mealy状态机。要特别注意的是,因为Mealy状态机和输入有关,输出会受到输入的干扰,所以可能会产生毛刺(Glitch)现象,使用时应当注意。在这个项目中,我们要用到Mealy状态机。
下面我们来分析在注释转换中都会遇到哪些问题:
1.一般情况
/* int i = 0; */
2.换行问题
/* 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*/
#include <stdio.h>
#include <errno.h>
#include <assert.h>
typedef enum STATE
{
SUCCESS, // 成功
FILE_ERROE, // 文件错误
NO_MATCH, // 不匹配
OTHER, // 其他错误
}STATE;
typedef enum TAG
{
TAG_BEGIN, // 在C注释段中
TAG_END, // C注释结束
}TAG;
#pragma warning(disable:4996)//使其在VS平台下不报错
STATE AnnotationConvert(FILE* inFile, FILE* outFile)
{
TAG tag = TAG_END;
char firstCh, secondCh;//定义两个字符变量,接收从文件中获取的字符串
char nextch;
assert(inFile);//检查指针的有效性
assert(outFile);//检查指针的有效性
do{
firstCh = fgetc(inFile);
switch (firstCh){
case '/'://处理一般情况和匹配情况
secondCh = fgetc(inFile);
if (secondCh == '*'
&& tag == TAG_END)//当情况为开始注释且不在注释中
{
fputc('/', outFile);
fputc('/', outFile);
tag = TAG_BEGIN;
}
else
{
fputc(firstCh, outFile);
fputc(secondCh, outFile);
if(secondCh=='/')//处理C++注释情况:// /*abcdefgh*/
{
nextch=fgetc(inFile);
do
{
nextch = fgetc(inFile);
fputc(nextch, outFile);
} while (nextch != '\n' && nextch != EOF);
}
}
break;
case '\n':
fputc(firstCh, outFile);
if(tag == TAG_BEGIN)//处理多行注释情况
{
fputc('/', outFile);
fputc('/', outFile);
}
break;
case '*':
secondCh = fgetc(inFile);
if (secondCh == '/')
{
nextch = fgetc(inFile);
tag = TAG_END;
fputc('\n', outFile);
if (nextch =='/')//处理换行问题/*int i = 0;*/ in t j = 0;
{ //以及连续注释/**//**/情况
fseek(inFile,-1,SEEK_CUR);
}
else if (nextch != '\n')
{
fputc(nextch, outFile);
}
}
else//处理连续**/情况:/********/
{
fputc(firstCh,outFile);
fseek(inFile,-1,SEEK_CUR);
}
break;
default:
fputc(firstCh, outFile);
break;
}
}while(firstCh != EOF);
if(tag == TAG_END)
{
return SUCCESS;
}
else
{
return NO_MATCH;
}
}
int StartConvert()
{
STATE s;
const char* inFileName = "input.c";
const char* outFileName = "output.c";
FILE* inFile = fopen(inFileName, "r");
FILE* outFile = fopen(outFileName, "w");
if (inFile == NULL)
{
return FILE_ERROE;
}
if (outFile == NULL)
{
fclose(inFile);
return FILE_ERROE;
}
s = AnnotationConvert(inFile, outFile);
fclose(inFile);
fclose(outFile);
return s;
}
int main()
{
STATE ret = StartConvert();
if (ret == SUCCESS)
{
printf("转换成功\n");
}
else if (ret == NO_MATCH)
{
printf("不匹配\n");
}
else if (ret == FILE_ERROE)
{
printf("文件错误: %d\n", errno);
}
else
{
printf("其他错误: %d\n", errno);
}
return 0;
}