个人项目:wc程序(java)
??Github項目地址:https://github.com/jat0824/wc.git
?項目相關要求
wc.exe 是一個常見的工具,它能統計文本文件的字符數、單詞數和行數。這個項目要求寫一個命令行程序,模仿已有wc.exe 的功能,并加以擴充,給出某程序設計語言源文件的字符數、單詞數和行數。實現一個統計程序,它能正確統計程序文件中的字符數、單詞數、行數,以及還具備其他擴展功能,并能夠快速地處理多個文件。具體功能要求:程序處理用戶需求的模式為:
wc.exe [parameter] [file_name]?
?
PSP
?
| Planning | 計劃 | ?60 | 30? | 
| · Estimate | · 估計這個任務需要多少時間 | ?700 | 630? | 
| Development | 開發 | ?640 | 590? | 
| · Analysis | · 需求分析 (包括學習新技術) | ?90 | 90? | 
| · Design Spec | · 生成設計文檔 | ?30 | 30? | 
| · Design Review | · 設計復審 (和同事審核設計文檔) | ?30 | 30? | 
| · Coding Standard | · 代碼規范 (為目前的開發制定合適的規范) | ?20 | 15? | 
| · Design | · 具體設計 | ?30 | 25? | 
| · Coding | · 具體編碼 | ?200 | 180? | 
| · Code Review | · 代碼復審 | ?60 | 40? | 
| · Test | · 測試(自我測試,修改代碼,提交修改) | ?180 | 180? | 
| Reporting | 報告 | ?120 | 100? | 
| · Test Report | · 測試報告 | ?60 | 60? | 
| · Size Measurement | · 計算工作量 | ?30 | 20? | 
| · Postmortem & Process Improvement Plan | · 事后總結, 并提出過程改進計劃 | ?30 | 20? | 
| ? | 合計 | ?820 | 720? | 
?
?
遇到的困難及解決方法
-  
問題描述做過的嘗試
- 1、關于如何將參數傳入main方法的問題
 - 2、如何統計詞數
 - 3、如何判別注釋段是否結束
 - 4、通配符的處理
 
 
- 做過的嘗試
-  
1、用Scanner類獲取參數輸入->使用main函數的argv數組獲取參數輸入
 -  
2、逐行讀取文件,除去特殊字符后用空格分離該行,返回數組長度
 -  
3、設置了兩個變量來記錄注釋段的開始字符個數和結束字符個數,只有兩個變量相等的時候才表示注釋段結束
 -  
4、將通配符按正則表達式的規則替換掉了*和?
 
 -  
 -  
成功解決問題
 -  
收獲:了解了main函數參數的作用,學習并運用了正則表達式,多角度思考問題
 
?
設計實現過程
包含以下幾個函數:
1、stringcount():實現-c、-l操作:統計文件字符數或行數
2、wordcount():實現-w操作:統計指定文件中詞的個數
3、handleall():實現-s操作:遞歸讀取目錄下符合條件的文件,加入List
4、moredata? ()? :實現-a操作: 統計代碼行/空行/注釋行
5、Checkfile? ()? :判斷需要處理的是目錄還是文件
6、deal? ()? :按正則表達式處理含通配符的文件名
7、main():主方法
實現過程:
在主方法中判斷輸入的參數并進行相應的操作,-s操作需要先調用Checkfile? () 函數,在Checkfile? () 函數中調用了deal? () 函數規范文件名,然后再調用了handleall()函數處理符合條件的文件。
?
?
?關鍵代碼
?-s、-a操作實現:
在主函數中:首先判斷參數是否為-s,然后調用Checkfile()方法判斷輸入的最后一個參數是目錄還是文件,最后通過handleall()方法對符合條件的文件進行后續操作。
?
// 判斷需要處理的是目錄還是文件 public static void Checkfile() {int pathlen = filename.get(0).length();int filelen = 0;String name = null;String file = filename.get(0);// 判斷是否為文件名,是否含有通配符if (file.replaceAll("[^//.^//*^//?]", "").length()==0) {handleall(file, "");}else{if (file.contains("/")){String[] n = file.split("/");name = n[n.length-1];filelen = name.length();handleall(file.substring(0, pathlen-filelen), deal(name));}else{handleall("", deal(file));}} }// 實現-s操作:遞歸讀取目錄下符合條件的文件,加入List public static List<String> handleall(String path, String name) {Matcher m = null;if (path.equals("")){dir = new File("src");}else {dir = new File(path);}File[] files = dir.listFiles();if (files == null){System.out.println("該目錄為空!");}for (File f : files){if (f.isFile()) {if (name.equals("")){filename.add(f.getAbsolutePath());}else {Pattern p = Pattern.compile(name);m = p.matcher(f.getName());if (m.matches()){filename.add(f.getAbsolutePath());}}}else if (f.isDirectory()) {handleall(f.getAbsolutePath(), name);}}return filename; }// 按正則表達式處理含通配符的文件名 public static String deal(String name) {name = name.replace(".", "#");name = name.replaceAll("#", "\\.");name = name.replace("*", "#");name = name.replaceAll("#", ".*");name = name.replace("?", "#");name = name.replaceAll("#", ".?");name = "^" + name + "$";// System.out.println(name);return name; }// 實現-a操作public static String moredata(int first) throws IOException {int line = 0;int null_line = 0; // 空行// 用于匹配注釋段的起始(/*)與結束(*/),只有當cp1==cp2時注釋段才結束int cp1 = 0; int cp2 = 0;// 標記整段注釋的起始行數int note = 0; int end = 0;int note_line = 0; // 注釋行int code_line = 0; // 代碼行File files = new File(filename.get(first));if (files.exists()) { // 判斷文件是否存在BufferedReader br = new BufferedReader(new FileReader(files));String st = null;while ((st = br.readLine())!=null) { // 如果文件中最后一行為空行則最后一行不算一行++line;// 將字符串中的空格、回車、換行符、制表符去掉String s = st.replaceAll("\\s*|\t|\r|\n", ""); if (s.equals("") || s.equals("{") || s.equals("}")) { // 判斷空行用s.equals("")// 注釋段中的空行不算在空行數中,算在注釋行數中if (s.equals("") && cp1!=cp2){;}else {null_line++;}}else if (s.startsWith("//") || s.startsWith("{//") || s.startsWith("}//")){note_line++;}else if (s.startsWith("/*")){cp1++;if (line>note && note!=0){continue;}else {note = line;}}else if (s.endsWith("*/")) {cp2++;if (line>end){end = line;}else {continue;}if (cp2 == cp1){note_line += end-note+1;}}// 代碼行=總行數-注釋行-空行code_line = line-note_line-null_line;}br.close();System.out.println("文件" + filename.get(first) + "的代碼行/空行/注釋行 分別為: " + code_line + "/" + null_line + "/" + note_line);return code_line + "/" + null_line + "/" + note_line;} else {System.out.println(files.getPath() + " 文件不存在!");return "no such file!";}}?
-  
Checkfile()方法用于判斷輸入的路徑是目錄還是文件,再通過handleall()方法將各符合條件的文件絕對路徑存入List表中。輸入的是目錄則遞歸對該目錄下的所有文件進行后續操作,輸入的是文件則直接對符合條件的文件進行后續操作(默認的文件路徑在src目錄下)
 -  
deal()方法是按正則表達式的規則處理含通配符的文件名,例如:輸入的文件名為 *.?d 則經過處理后文件名為 ^.*..?d$
 
-  
- 其中^和$分別表示正則表達式的起始和終止
 - ?. 匹配除"\r\n"之外的任何單個字符; * 表示零次或多次匹配前面的字符或子表達式; ?表示零次或一次匹配前面的字符或子表達式;
 
 
-  
moredata()方法中實現了對代碼行、空行、注釋行的統計,其中注釋行的統計主要設置了兩個int類變量cp1和cp2 對讀取的每一行字符串進行判斷,是否為"/*"開頭,是則cp1++,是否為"*/"結尾,是則cp2++。因此只有當cp1==cp2的時候注釋段才結束,這樣設計主要針對注釋段中含有注釋段的特殊情況。并且注釋段中的空行算在注釋行數不算在空行數。
 -  
運行結果截圖:
-  
輸入命令:
 -  
結果輸出:
 
 -  
 
?
測試運行
運行測試單元文件,運行結果截圖:
?
項目小結
? ?在一開始分析需求的時候沒有徹底分析清楚需求,導致設計的時候沒有考慮全面,在快結束的時候才發現需求沒有完全實現。而且有些功能會有些不能解決的情況,例如:-w功能統計詞數的時候如果兩個詞都頂格,分布在相鄰兩行或者中間隔著若干空行,則該功能會將兩個詞算為一個詞。下次開發的時候不能粗略的按照自己的理解看完需求就馬上開始設計,應該認真的看完需求文檔之后再進行設計。在代碼規范方面,應該在平時寫代碼的時候就養成好習慣,在需要解釋說明的地方寫好注釋,代碼的格式也應該有自己的風格。在開發完后可以給自己的項目寫個用戶說明文檔以便用戶使用。
?
?
?
轉載于:https://www.cnblogs.com/x-j1/p/9648250.html
總結
以上是生活随笔為你收集整理的个人项目:wc程序(java)的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: Solr 访问 403 错误
 - 下一篇: WOJ 18 动态无向图