最近做了一個註釋轉換的項目,將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;
}