2016-03-04 61 views
1

我正在研究一個讀取包含不正確縮進代碼的5個不同文件的程序。我必須編寫一個方法,將代碼正確縮進並將其打印到控制檯和一個新文件,並給定製表符大小以及輸入和輸出文件的名稱作爲參數。我的代碼到目前爲止貫穿並縮進每一行,然後嘗試確定何時縮進另一個選項卡或取消縮進。更改文件中的每一行 - Java

public static void justifyJava(String inputFileName, String outputFileName, 
           int tabSize) throws FileNotFoundException { 

    String one_tab = ""; 
    for (int i = 0; i < tabSize; i++) { 
     one_tab += " "; 
     } 

    Scanner input = new Scanner(new File (inputFileName)); 
    PrintStream out = new PrintStream (new File (outputFileName)); 
    int lineCount = 0; 
    while (input.hasNextLine()) { 
     String line = input.nextLine(); 
     line = one_tab + line.trim(); 
     lineCount++; 
     if (lineCount == 1){ 
      line = line.substring(tabSize); 
     } 
     else if (lineCount == 2){ 
      Scanner lineScan = new Scanner(line); 
      while (lineScan.hasNext()) { 
       String token = lineScan.next(); 
       if (token.length() <= 2) { 
        line = line.substring(tabSize); 
       } 
      } 
     } 
     else if (line.contains("{") && lineCount > 2){ 
      System.out.println(line); 
      out.println(line); 
      line = one_tab + input.nextLine(); 
      while(!(line.contains("}"))){ 
       line = one_tab + line; 
       System.out.println(line); 
       out.println(line); 
       line = input.nextLine(); 
      } 
      line = one_tab + line; 
     } 
     else if (line.contains("}") && input.hasNextLine()){ 
      line = one_tab + line; 
     } 
     else if (!(input.hasNextLine())) { 
      line = line.substring(tabSize); 
     } 
     System.out.println(line); 
     out.println(line);          
    }    
} 

這種方式正在成爲,因爲我有多少的情況下考慮到特別是因爲這些文件中的代碼中使用不同的花括號風格非常繁瑣。基本上我所要做的就是縮進每一行,後面跟着一個選項卡的開啓大括號,以及每個按照一個選項卡關閉大括號的每一行。有沒有更簡單的方法來做到這一點?

+3

每種語言都可能有成千上萬的漂亮打印機。所以,除非這是家庭作業/學習練習,否則沒有理由這麼做......查找工具(如果您的編輯器因爲某些原因沒有這樣的功能)絕對更容易(並且可能更加正確)。 –

+0

完全同意阿列克謝。但如果這不是,請考慮這個 - http://stackoverflow.com/questions/27275272/replacing-tab-characters-in-java-files-with-4-spaces – stdunbar

+0

遞歸是去這裏的路。每當你檢測到你不得不深入縮進時,你都會輸入遞歸。 – jcmonteiro

回答

0

確定「多少次」您不得不縮進一條線與知道在這條線之前打開多少塊代碼相同。爲此,如果檢測到新的代碼塊:

  1. 該字符串包含一個左括號{。
  2. 該字符串包含控制語句,例如, if

第二種方法比較困難,因爲您必須確定字符串是否實際上是控制語句而不是變量名的一部分。

因此,一個簡單的程序,這並不涵蓋所有可能的編碼標準,但會工作得體面工作原理是這樣:

  1. 搜索不屬於評論的左括號。
  2. 當您找到它時,遞歸調用傳遞新縮進大小的方法。
  3. 找到代碼塊結束後返回。

這裏有一個適用於大多數簡單情況的MWE。它能夠檢測字符串外部的開啓和關閉括號,並且不會在註釋行中進行搜索。

import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.PrintStream; 
import java.util.ArrayList; 
import java.util.Scanner; 


public class JavaIndent { 

    public static void main(String[] args) { 
     try { 
      JavaIndent.justify("path/to/input.java", "path/to/output.java", 4); 
     } catch (FileNotFoundException ex) { 
      System.out.println("File not found..."); 
     } 
    } 

    public static void justify(String inputFileName, String outputFileName, 
      int tabSize) throws FileNotFoundException { 

     String one_tab = ""; 
     for (int i = 0; i < tabSize; i++) { 
      one_tab += " "; 
     } 

     Scanner input = new Scanner(new File(inputFileName)); 
     PrintStream out = new PrintStream(new File(outputFileName)); 

     JavaIndent.justifyRecursion(one_tab, "", input, out); 
    } 

    private static String justifyRecursion(String base_tab, String tab, Scanner input, PrintStream out) { 
     String line; 
     boolean flag_open, flag_close, flag_comment, flag_empty; 
     while (input.hasNextLine()) { 
      line = input.nextLine().trim(); 
      flag_open = JavaIndent.contains(line, "{"); 
      flag_close = JavaIndent.contains(line, "}"); 
      flag_empty = line.length() == 0; 
      flag_comment = (flag_empty) ? false : line.charAt(0) == '/'; 
      if (flag_comment || flag_empty) { 
       out.println(tab + line); 
      } else if (flag_close) { 
       return line; 
      } else if (flag_open) { 
       out.println(tab + line + "ENTERED OPEN"); 
       line = JavaIndent.justifyRecursion(base_tab, tab + base_tab, input, out); 
       out.println(tab + line); 

       // Handles statements like } else { and sequences of these. 
       flag_open = JavaIndent.contains(line, "{"); 
       while (flag_open) { 
        line = JavaIndent.justifyRecursion(base_tab, tab + base_tab, input, out); 
        out.println(tab + line); 
        flag_open = JavaIndent.contains(line, "{"); 
       } 
      } else { 
       // Just a regular line, nothing special 
       out.println(tab + line); 
      } 
     } 
     return ""; 
    } 

    private static boolean contains(String line, String sequence) { 
     String current = ""; 
     char ch, last_ch = ' '; 
     int count_quotation = 0; 
     ArrayList<String> code_without_strings = new ArrayList<>(); 
     for (int k = 0; k < line.length(); ++k) { 
      ch = line.charAt(k); 
      if (ch == '"' && count_quotation == 0 && last_ch != '\'') { 
       code_without_strings.add(current); 
       current = ""; 
       ++count_quotation; 
      } else if (ch == '"' && count_quotation == 1) { 
       if (last_ch != '\\') { 
        count_quotation = 0; 
       } 
      } 
      if (count_quotation == 0) { 
       current += ch; 
      } 
      last_ch = ch; 
     } 
     code_without_strings.add(current); 

     for (String code : code_without_strings) { 
      if (code.contains(sequence)) 
       return true; 
     } 
     return false; 
    } 
} 

但是,我們仍然需要考慮這樣的語句:

if (condition) 
    System.out.println("This should be indented, but it won't be..."); 

這:

/** 
* This is just a comment, but the program will indent from here on {. 
*/ 

嘗試使用JavaIndent縮進JavaIndent.java並驗證在很結束您將獲得

if (code.contains(sequence)) 
return true; 

而不是

if (code.contains(sequence)) 
    return true;