【18.8.7】C語言註釋向C++註釋的轉化
阿新 • • 發佈:2018-11-20
C語言註釋對比C++註釋,功能要明顯差一些,因此,當程式中需要將C語言的註釋轉化時,就需要一個註釋的轉化軟體。畢竟對於大量的程式碼,我們不可能一個一個的去更改。
在程式設計初期,我們應該想到,對於C註釋開始的識別,但會牽扯的/是除號。或者別的用途,包括結束時,*號的識別。做一個簡單的情況分析後,總結出,將其各種情況,用一個狀態機去解決。這樣可以將無限種的可能,轉化為有限種的情況。文字狀態,C語言註釋的狀態,C++註釋的狀態,和結束文字的標誌(EOF)。
文字狀態
遇到了‘/*’就開始進入了C語言的註釋狀態
遇到了‘//’就開始的C++的註釋狀態
遇到了‘EOF’代表我的文字已經讀取結束
C語言註釋狀態
遇到‘*/’結束,進入文字狀態
C語言不支援巢狀註釋,所以裡面也不會進入C++註釋狀態
C語言註釋在文字結束前一定會‘*/’結束,不會再結束註釋前就EOF退出
C++註釋狀態
當著一行註釋結束時,C語言註釋就結束,也就是遇到‘/n’結束
當註釋中找到EOF檔案結束標誌,證明這行就是最後一行,直接結束
同理,在C++註釋中也不會跳到C語言的註釋
結束標誌EOF
結束都結束了,也就不談轉入別的狀態了好吧
解決完這個就是開始碼程式碼。同樣使用多個.c檔案,將程式碼拆開寫。這樣問題比較容易找出。先是測試的test.c檔案。
test.c
#include"Annotation.h"//印一下.h的標頭檔案
void test()
{
FILE * pread = NULL;
FILE * pwrite = NULL;
pread = fopen("HeadsomeYZX.txt","r");//從流中讀取文字內容,這裡的。txt檔名是亂起的,就是輸入檔案,就是已經有的文字
if(pread == NULL)
{
printf("Error opening read");//解決讀取失敗。
exit(EXIT_FAILURE);
}
pwrite = fopen("SomelyMYT.txt","w");//從流中寫一個檔案
if(pwrite == NULL)
{
printf("Error opening write");
exit(EXIT_FAILURE);
}
AnnCtoCPP(pread,pwrite);//核心的轉換功能,將他寫到核心.c檔案中
fclose(pread);//結束流
pread = NULL;//指標指向空
fclose(pwrite);
pwrite = NULL;
}
int main()
{
test();
return 0;
}
Annotation.c
核心檔案
#include"Annotation.h"
void AnnCtoCPP(FILE *pread,FILE *pwrite)
{
State state = text_state;//初始化狀態,初始化為文字狀態
while(state != end_state)//只有讀取到文字並非結束狀態時進入狀態選擇
{
switch(state)
{
case c_state:
Annotationc_cPP(pread,pwrite,&state);//進入c註釋轉化為c++註釋狀態
break;
case text_state:
Annotationtext_cPP(pread,pwrite,&state);//進入文字狀態
break;
case cPP_state:
NOTAnnotation(pread,pwrite,&state);//進入C++註釋狀態
break;
}
}
}
void Annotationc_cPP(FILE *pread,FILE *pwrite,State *p)
{
int first = fgetc(pread);//先讀一個字元
switch(first)
{
case '*'://讀到*,開始敏感,因為可能是遇到了C註釋的結束
{
int second = fgetc(pread);
switch(second)
{
case '/'://cPP註釋結束。
{
int third = fgetc(pread);//判斷後面還有沒有內容
if(third == '\n')//後面無內容
{
fputc(third,pwrite);
}
else
{
fputc('\n',pwrite);//註釋結束了,但是後面有內容,將其換行列印
ungetc(third,pread);
}
*p = text_state;
}
break;
case '*'://這是一個特殊狀態,即/***/讀到*,後下一個不是/,繼續讀,可能錯過*/的結束標誌
{
fputc(first,pwrite);
ungetc(second,pread);//將其返回文字中,下一次繼續從這裡讀
}
break;
default :
{
fputc(first,pwrite);
ungetc(second,pread);
}
break;
}
}
break;
case '\n'://在C語言的註釋中如果遇到\n就換行,在輸出兩個/
{
fputc(first,pwrite);
fputc('/',pwrite);
fputc('/',pwrite);
}
break;
default ://後面什麼都不是就代表,這個*不是註釋的結束
{
fputc(first,pwrite);
}
break;
}
}
void Annotationtext_cPP(FILE *pread,FILE *pwrite,State *p)
{
int first = fgetc(pread);
switch(first)
{
case '/'://文字狀態讀取到/開始敏感,可能進入註釋狀態
{
int second = fgetc(pread);
switch(second)
{
case '*'://遇到*進入C語言註釋狀態,把他轉化成//的C++註釋狀態
{
fputc('/',pwrite);
fputc('/',pwrite);
*p = c_state;//進入C語言註釋狀態,去尋找註釋結束標誌
}
break;
case '/'://遇到/進入C++註釋狀態
{
fputc('/',pwrite);
fputc('/',pwrite);
*p = cPP_state;
}
break;
default ://後面不是代表/只是別的功能
{
fputc(first,pwrite);
fputc(second,pwrite);
}
break;
}
}
break;
case EOF://文字遇到EOF,結束文字
{
fputc(first,pwrite);
*p = end_state;
}
break;
default ://正常列印文字
fputc(first,pwrite);
break;
}
}
void NOTAnnotation(FILE *pread,FILE *pwrite,State *p)
{
int first = fgetc(pread);
switch(first)
{
case '\n'://C++註釋換行就意味著結束註釋
{
fputc(first,pwrite);
*p = text_state;
}
break;
case EOF://遇到EOF結束檔案
*p = end_state;
break;
default :
fputc(first,pwrite);
break;
}
}
Annotation.h
標頭檔案
#ifndef __AnnotationCtoCPP_H__
#define __AnnotationCtoCPP_H__
#include <stdio.h>
#include <stdlib.h>
typedef enum //使用列舉,狀態機
{
text_state,
c_state,
cPP_state,
end_state
}State;//重新命名,這樣後面寫程式碼,可以少寫一些
void AnnCtoCPP(FILE *pread,FILE *pwrite);
void Annotationc_cPP(FILE *pread,FILE *pwrite,State *pstate);
void Annotationtext_cPP(FILE *pread,FILE *pwrite,State *pstate);
void NOTAnnotation(FILE *pread,FILE *pwrite,State *pstate);
#endif
測試一下功能
例子貌似不夠刁鑽啊。那來個刁鑽測試用例