本次這個小項目的目的是把.c文件中的C風格的注釋轉換成為C++風格的注釋。
C注釋風格:/**/
C++注釋風格://
首先我們分析一下會出現的幾種狀態,以及各種狀態之間的轉換關系:
首先我們在這裡對一些狀態進行了標注,我們這裡已知的有4種狀態,
第一種是END_STATE
第二種是C_STATE
第三種是CPP_STATE
第四種是我們平時的NULL_state。
在這裡,注釋轉換操作的是文件,所以接下來我麼采用文件操作。
首先我們要打開input.c文件,對這個文件內部的文件進行讀取,然後處理,否則直接提示用戶有錯誤。
接下來,我們還要打開output.c文件,對處理以後的代碼進行寫入。
接下來,我們就要分析各種可能會遇到的情況:
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*/
在這裡我們對這個小項目編寫的方法和我們前面對通訊錄的方式是一樣的,采用三個文件封裝,一個test.c文件封裝測試文件,一個comment_covert.c文件封裝實現函數,一個comment_covert.h文件封裝頭文件。
在這裡對待每一個狀態,我們就可以采取枚舉常量。
static enum STATE
{
NULL_STATE,
C_STATE,
CPP_STATE,
END_STATE
};
然後你要清楚,現在我們所要處理的默認狀態是從NULL_STATE,所以接下來我們實現NULL_STATE函數,然後我們借助上面我所繪制的各種狀態之間的轉換關系,我們可以知道,在這裡我們最需要判斷的是所檢察的第一個字符是什麼,在這裡有三種情況:‘/’,普通字符,EOF,所以我們先要接收第一個字符,然後利用我們的有限狀態機,當為’/’時,我們進行下一個字符的判斷,判斷是否為‘*’,如果是,那麼我們接下來讓state為C_STATE,如果是‘/’那麼進入CPP_state,接下來,其他字符,按照限定自行做出編輯即可。
#ifndef __COMMENT_CONVERT_H
#define __COMMENT_CONVERT_H
#include
#include
#define READFILENAME "input.c"
#define WRITEFILENAME "output.c"
static enum STATE
{
NULL_STATE,
C_STATE,
CPP_STATE,
END_STATE
};
void CommentConvert(FILE *fRead, FILE *fWrite);
void Do_C_State(FILE *fRead, FILE *fWrite);
void Do_CPP_State(FILE *fRead, FILE *fWrite);
void Do_Null_state(FILE *fRead, FILE *fWrite);
#endif //!__COMMENT_CONVERT_H
#define _CRT_SECURE_NO_WARNINGS 1
#include"comment_covert.h"
enum STATE state = NULL_STATE;
void Do_C_State(FILE *fRead, FILE *fWrite)
{
char first = 0;
char second = 0;
char third = 0;
first = fgetc(fRead);
switch (first)
{
case'*':
second = fgetc(fRead);
switch (second)
{
case'/':
third = fgetc(fRead);
if (third != '\n')
fputc('\n', fWrite);
if (third == '/')
{
ungetc(third, fRead);
state = NULL_STATE;
break;
}
fputc(third, fWrite);
state = NULL_STATE;
break;
case'*':
third = fgetc(fRead);
fputc(first, fWrite);
if (third == '/')
{
state=NULL_STATE;
}
break;
default:
fputc(first, fWrite);
fputc(second, fWrite);
break;
}
break;
case'\n':
fputc(first, fWrite);
fputc('/', fWrite);
fputc('/', fWrite);
break;
case EOF:
state = END_STATE;
break;
default:
fputc(first, fWrite);
break;
}
}
void Do_CPP_State(FILE *fRead, FILE *fWrite)
{
char first = 0;
first = fgetc(fRead);
switch (first)
{
case '\n':
fputc(first, fWrite);
state = NULL_STATE;
break;
case EOF:
state = END_STATE;
break;
default:
fputc(first, fWrite);
break;
}
}
void Do_Null_state(FILE *fRead, FILE *fWrite)
{
char first = 0;
char second = 0;
first = fgetc(fRead);
switch (first)
{
case'/':
second = fgetc(fRead);
if (second == '*')
{
fputc('/', fWrite);
fputc('/', fWrite);
state = C_STATE;
}
else if (second == '/')
{
fputc(first, fWrite);
fputc(second, fWrite);
state = CPP_STATE;
}
else
{
fputc(first, fWrite);
fputc(second, fWrite);
}
break;
case EOF:
state = END_STATE;
break;
default:
fputc(first, fWrite);
break;
}
}
void CommentConvert(FILE *fRead, FILE *fWrite)
{
while (state!=END_STATE)
{
switch (state)
{
case NULL_STATE:
Do_Null_state(fRead, fWrite);
break;
case C_STATE:
Do_C_State(fRead, fWrite);
break;
case CPP_STATE:
Do_CPP_State(fRead, fWrite);
break;
default:
break;
}
}
}
#define _CRT_SECURE_NO_WARNINGS 1
#include"comment_covert.h"
int main()
{
FILE *fRead = NULL;
FILE *fWrite = NULL;
printf("*****注釋轉換開始******\n");
fRead = fopen(READFILENAME, "r");
if (NULL == fRead)
{
perror("read of file");
exit(EXIT_FAILURE);
}
fWrite = fopen(WRITEFILENAME, "w");
if (NULL == fRead)
{
fclose(fRead);
perror("write of file");
exit(EXIT_FAILURE);
}
CommentConvert(fRead, fWrite);
printf("*****注釋轉換結束******\n");
fclose(fRead);
fclose(fWrite);
system("pause");
return 0;
}
最終就可以完成這個小項目了,代碼的分析需要一步一步來,想要解決問題,也不能急,一步一步分析,哪怕最費勁的進行單步調試。