在写代码之前,我们先来看一个概念,即有限转状态机(Finite-state machine, FSM)。
什么是有限状态机
有限状态机是一种数学模型,从字面意思理解,就是有有限个状态的机器。
我们可以想象一条传送带,上边有指示灯,比如说,这条传送带,是将产品的良品和次品分开,那么良品和次品就是产品会出现的两种状态,它只有这两种状态,要么是良品,要么是次品。这就是有限个状态。
有限状态机就表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。
注释转换
我们利用有限状态机的思想来分析注释转换,C语言里可能会出现C语言的注释,也C++的注释。因此,我们将它分为以下五种情况:
分析好之后,我们只需想其中的状态转换 之间填充代码,这样思路就会清晰很多。
#include <stdio.h>
#include <string.h>
#include <assert.h>
#pragma warning(disable:4996)
typedef enum State
{
NORMAL, //不是注释
Find_Slash, //有可能进入注释
CPP_Comment, //C++注释
C_Comment, //C注释
Find_Star //有可能出C注释
}State;
int main()
{
FILE* pIn = fopen("input.c", "r");
assert(pIn);
FILE* pOut = fopen("output.c", "w");
assert(pOut);
State state = NORMAL;
char ch, Nextch;
while (1)
{
ch = fgetc(pIn);
if (ch == EOF)
break;
switch (state)
{
case NORMAL:
if (ch == '/')
state = Find_Slash;
else
state = NORMAL;
fputc(ch, pOut);
break;
case Find_Slash:
if (ch == '*')
{
state = C_Comment;
fputc('/',pOut);
}
else if (ch == '/')
{
state = CPP_Comment;
fputc('/', pOut);
}
else
{
state = NORMAL;
fputc(ch, pOut);
}
break;
case C_Comment:
if (ch == '*')
{
Nextch = fgetc(pIn);
state = Find_Star;
//如果下一个字符是‘/’说明要出注释,不打印
//否则,打印
if (Nextch != '/')
fputc(ch, pOut);
ungetc(Nextch, pIn);
}
else
{
state = C_Comment;
if (ch == '\n')
{
fputc(ch, pOut);
fputc('/', pOut);
fputc('/', pOut);
}
else
{
fputc(ch, pOut);
}
}
break;
case CPP_Comment:
if (ch == '\n')
state = NORMAL;
else
state = CPP_Comment;
fputc(ch, pOut);
break;
case Find_Star:
if (ch == '/')
{
state = NORMAL;
Nextch = fgetc(pIn);
if (Nextch != '\n')
{
fputc('\n', pOut);
}
ungetc(Nextch, pIn);
}
else if (ch == '*')
{
fputc(ch, pOut);
state = Find_Star;
}
else
{
state = C_Comment;
fputc(ch, pOut);
}
break;
default:
break;
}
}
fclose(pIn);
fclose(pOut);
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++注释问题
// /*xxxxxxxxxxxx*/
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++注释问题
// /*xxxxxxxxxxxx*/