狀態機器編程思想(2):刪除代碼注釋(目前支援C/C++和Java),編程思想java

來源:互聯網
上載者:User

狀態機器編程思想(2):刪除代碼注釋(目前支援C/C++和Java),編程思想java
前言

有時為了資訊保密或是單純閱讀代碼,我們需要刪除注釋。

之前考慮過Regex,但是感覺實現起來相當麻煩。而狀態機器可以把多種情況歸為一類狀態再行分解,大大簡化問題。本文就是基於狀態機器實現的。

目錄
  • 刪除C/C++代碼注釋
  • 刪除Java代碼注釋
  • 程式
  • 參考
刪除C/C++代碼注釋需要考慮的情況
  • //
  • /* */
  • //和/* */嵌套(注意不存在/* */和/* */嵌套)
  • 折行注釋(用\間隔)
  • 字元中存在的/和*
  • 字串中存在的//和/* */
  • 字串中的折行代碼(用\間隔)
  • 標頭檔中可能存在的/
狀態轉移描述

思路參考了部落格http://www.cnblogs.com/zhanghaiba/p/3569928.html#3853787,寫得很贊。

本文基於上面所述博文進行了以下修改或是最佳化:

  • 原博文沒有考慮/***/的情況(其中*的個數為奇數),已修正
  • 切換到了windows平台下,支援windows換行\r\n(並請注意:如果原檔案末尾沒有斷行符號,會自動插入)
  • 狀態量最佳化為枚舉常量
  • 狀態轉移由if...else...elseif結構改為switch...case結構,更為清晰,對於大型代碼,效率更高

 

 

 其中,除狀態NOTE_MULTILINE_STAR外,其餘狀態下均需進行字元(串)處理,以保持正確輸出。詳見文末代碼。

 

刪除Java代碼注釋需要考慮的情況
  • //
  • /* */
  • /** */
  • //和/**/嵌套(注意不存在/* */和/* */嵌套,不存在/** */和/** */嵌套,不存在/* */和/** */嵌套)
  • //和/** */嵌套
  • 字元中存在的/和*
  • 字串中存在的//、/**/以及/** */
狀態轉移描述

 可以看到,java中的注釋規則更為簡單,其中/** */完全可以用/* */的狀態涵蓋。且不會出現折行注釋和字串折行的情況,因此狀態更加簡單,有興趣的可以畫一畫,這裡就不畫圖了。換句話說,上面刪除C/C++注釋的程式完全可以用來刪除java注釋。

 

程式

 

  1 import java.io.FileInputStream;  2 import java.io.InputStreamReader;  3 import java.io.BufferedReader;  4   5 import java.io.FileOutputStream;  6 import java.io.OutputStreamWriter;  7 import java.io.BufferedWriter;  8   9 import java.io.IOException; 10  11 import java.util.Scanner; 12  13 /** 14  * @author xiaoxi666 15  * @version 1.0.0 2017.12.01 16  */ 17  18 public class deleteCAndCplusplusAndJavaNote { 19  20     /** 21      * 狀態 22      */ 23     enum State { 24         CODE, // 正常代碼 25         SLASH, // 斜杠 26         NOTE_MULTILINE, // 多行注釋 27         NOTE_MULTILINE_STAR, // 多行注釋遇到* 28         NOTE_SINGLELINE, // 單行注釋 29         BACKSLASH, // 折行注釋 30         CODE_CHAR, // 字元 31         CHAR_ESCAPE_SEQUENCE, // 字元中的逸出字元 32         CODE_STRING, // 字串 33         STRING_ESCAPE_SEQUENCE// 字串中的逸出字元 34     }; 35  36     /** 37      * @function 刪除代碼中的注釋,以String形式返回 38      * @param strToHandle 待刪除注釋的代碼 39      * @return 已刪除注釋的代碼,String字串形式 40      */ 41     public static String delete_C_Cplusplus_Java_Note(String strToHandle) { 42         StringBuilder builder = new StringBuilder(); 43  44         State state = State.CODE;// Initiate 45         for (int i = 0; i < strToHandle.length(); ++i) { 46             char c = strToHandle.charAt(i); 47             switch (state) { 48             case CODE: 49                 if (c == '/') { 50                     state = State.SLASH; 51                 }else { 52                     builder.append(c); 53                     if(c=='\'') { 54                         state=State.CODE_CHAR; 55                     }else if(c=='\"') { 56                         state=State.CODE_STRING; 57                     } 58                 }                     59                 break; 60             case SLASH: 61                 if (c == '*') { 62                     state = State.NOTE_MULTILINE; 63                 } else if (c == '/') { 64                     state = State.NOTE_SINGLELINE; 65                 } else { 66                     builder.append('/'); 67                     builder.append(c); 68                     state = State.CODE; 69                 } 70                 break; 71             case NOTE_MULTILINE: 72                 if(c=='*') { 73                     state=State.NOTE_MULTILINE_STAR; 74                 }else { 75                     if(c=='\n') { 76                         builder.append("\r\n");//保留空行,當然,也可以去掉 77                     } 78                     state=State.NOTE_MULTILINE;//保持目前狀態 79                 } 80                 break; 81             case NOTE_MULTILINE_STAR: 82                 if(c=='/') { 83                     state=State.CODE; 84                 }else if(c=='*') { 85                     state=State.NOTE_MULTILINE_STAR;//保持目前狀態 86                 } 87                 else { 88                     state=State.NOTE_MULTILINE; 89                 } 90                 break; 91             case NOTE_SINGLELINE: 92                 if(c=='\\') { 93                     state=State.BACKSLASH; 94                 }else if(c=='\n'){ 95                     builder.append("\r\n"); 96                     state=State.CODE; 97                 }else { 98                     state=State.NOTE_SINGLELINE;//保持目前狀態 99                 }100                 break;101             case BACKSLASH:102                 if(c=='\\' || c=='\r'||c=='\n') {//windows系統分行符號為\r\n103                     if(c=='\n') {104                         builder.append("\r\n");//保留空行,當然,也可以去掉105                     }106                     state=State.BACKSLASH;//保持目前狀態107                 }else {108                     state=State.NOTE_SINGLELINE;109                 }110                 break;111             case CODE_CHAR:112                 builder.append(c);113                 if(c=='\\') {114                     state=State.CHAR_ESCAPE_SEQUENCE;115                 }else if(c=='\'') {                    116                     state=State.CODE;117                 }else {118                     state=State.CODE_CHAR;//保持目前狀態119                 }120                 break;121             case CHAR_ESCAPE_SEQUENCE:122                 builder.append(c);123                 state=State.CODE_CHAR;124                 break;125             case CODE_STRING:126                 builder.append(c);127                 if(c=='\\') {128                     state=State.STRING_ESCAPE_SEQUENCE;129                 }else if(c=='\"') {                    130                     state=State.CODE;131                 }else {132                     state=State.CODE_STRING;//保持目前狀態133                 }134                 break;135             case STRING_ESCAPE_SEQUENCE:136                 builder.append(c);137                 state=State.CODE_STRING;138                 break;139             default:140                 break;141             }142         }143         return builder.toString();144     }145 146     /**147      * @function 從指定檔案中讀取代碼內容,以String形式返回148      * @param inputFileName 待刪除注釋的檔案149      * @return 待刪除注釋的檔案中的代碼內容,String字串形式150      * @note 輸入檔案格式預設為 UTF-8151      */152     public static String readFile(String inputFileName) {153         StringBuilder builder = new StringBuilder();154         try {155             FileInputStream fis = new FileInputStream(inputFileName);156             InputStreamReader dis = new InputStreamReader(fis);157             BufferedReader reader = new BufferedReader(dis);158             String s;159             // 每次讀取一行,當改行為空白時結束160             while ((s = reader.readLine()) != null) {161                 builder.append(s);162                 builder.append("\r\n");// windows系統分行符號163             }164             reader.close();165             dis.close();166             fis.close();167         } catch (IOException e) {168             e.printStackTrace();169             System.exit(1);170         }171         return builder.toString();172     }173 174     /**175      * @function 將刪除注釋後的代碼儲存到指定新檔案176      * @param outputFileName 儲存“刪除注釋後的代碼”的檔案的檔案名稱177      * @param strHandled 刪除注釋後的代碼178      */179     public static void writeFile(String outputFileName, String strHandled) {180         try {181             FileOutputStream fos = new FileOutputStream(outputFileName);182             OutputStreamWriter dos = new OutputStreamWriter(fos);183             BufferedWriter writer = new BufferedWriter(dos);184             writer.write(strHandled);185             writer.close();186             dos.close();187             fos.close();188             System.out.println("code that without note has been saved successfully in " + outputFileName);189         } catch (IOException e) {190             e.printStackTrace();191         }192     }193 194     /**195      * @function 讀取待處理檔案,刪除注釋,處理過的代碼寫入新檔案196      * @param args197      */198     public static void main(String[] args) {199         Scanner in = new Scanner(System.in);200         //待刪除注釋的檔案201         System.out.println("The fileName that will be delete note:");202         String inputFileName = in.nextLine();203         //儲存“刪除注釋後的代碼”的檔案204         System.out.println("The fileName that will save code without note:");205         String outputFileName = in.nextLine();206         207         String strToHandle = readFile(inputFileName);208         String strHandled = delete_C_Cplusplus_Java_Note(strToHandle);209         writeFile(outputFileName, strHandled);210         211     }212 213 }

 

說明
  • 本程式保留注釋佔用行,也就是說,注釋以外的代碼原樣保留(行數也不會變),注釋行變為空白。
  • 不檢測檔案尾碼(這就意味著把代碼寫在.txt裡面也可以處理),有需求的可以自行添加。
  • 本程式適用於windows平台,其他平台如linux和mac請替換“\r\n”分行符號。檔案格式預設為UTF。
  • 有興趣的可以封裝成圖形介面,直接拖入檔案處理,更好用。
  • 本程式經過大量測試未發現bug,若讀者發現bug,歡迎提出。

 

參考
  • 怎樣刪除C/C++代碼中的所有注釋?淺談狀態機器的編程思想: http://www.cnblogs.com/zhanghaiba/p/3569928.html#3853787 
  • 誰能寫出個刪除注釋的Regex:http://bbs.csdn.net/topics/380183706 
  • Regex刪除代碼的注釋: http://blog.csdn.net/conquer0715/article/details/14446463 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.