1. 程式人生 > >【18.8.7】C語言註釋向C++註釋的轉化

【18.8.7】C語言註釋向C++註釋的轉化

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

測試一下功能

這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

例子貌似不夠刁鑽啊。那來個刁鑽測試用例

這裡寫圖片描述
這裡寫圖片描述