2016-03-04 59 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;