在寫代碼之前,我們先來看一個概念,即有限轉狀態機(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*/