狀態機處理文本

/*
**刪除C/C++源代碼中的註釋
*/
#include <stdio.h>
int main( int argc, char *argv[] )
{
	//定義各種狀態
	enum{NONE,PRE_LINE,LINE,ALL,PREEND_ALL,ALL_END} state = NONE;
	char *fileinput, *fileoutput;
	FILE *fpinput, *fpoutput;
	int ch;

	if(argc != 3){
		printf("none of input and output file!");
		return -1;
	}
	//參數1爲輸入文件名,參數2爲輸出文件名
	fileinput = argv[1];
	fileoutput = argv[2];

	if((fpinput = fopen(fileinput,"r")) == NULL){
		printf("Open input file error!");
		return -1;
	}

	if((fpoutput = fopen(fileoutput,"w")) == NULL){
		printf("Open input file error!");
		return -1;
	}
	while( (ch = fgetc(fpinput)) != EOF)      //循環讀取文件中的字符
	{
		switch(ch)
		{
		case '/':
			if(state == NONE)
				state = PRE_LINE;
			else
			{
				if(state == PRE_LINE)
					state = LINE;
				else if(state == PREEND_ALL)
					state = ALL_END;
				
			}
			break;
		case '*':
			if(state == PRE_LINE)
				state = ALL;
			else
			{
				if(state == ALL)
					state = PREEND_ALL;
			}
			break;
		case '\n':
			if(state == LINE)
				state = NONE;
			break;
		default:
			if(state == ALL_END)
				state = NONE;
		}
		if(state == NONE)
			putc(ch,fpoutput);
	}
	putc(EOF,fpoutput);       //給輸出文件尾加EOF結束標誌

	fclose(fpoutput);
	fclose(fpinput);
}


 

以上代碼用enum定義了一些狀態,其中,NONE表示非註釋狀態,PRE_LINE表示在NONE狀態下遇到'/'字符,LINE表示PRE_LINE下遇到再'/'字符,ALL表示PRE_LINE狀態下遇到'*'字符,PREEND_ALL表示ALL狀態下遇到'*'字符,ALL_END表示PREEND_ALL狀態下遇到'/'字符。
通過這些狀態就可以很輕鬆的知道當前字符是否註釋,不是註釋就複製到輸出文件中。其實很多文本文件的處理,像刪掉含有某一字符串的行,查找某字符串,甚至高級點的像ini文件、xml文件都可以用狀態機實現。


注:其中ch變量聲明爲int類型是因爲EOF爲整形,如果ch爲char型,當ch和EOF的低位相等時,一比較的話,就會跳出循環,而實際上我們的文件還沒有結束,所以防止這類錯誤,聲明ch爲int型。

-------本人菜鳥一隻,如有不足,望大牛指出^_^

 

發佈了41 篇原創文章 · 獲贊 16 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章