【每日一题】PTA - L3-019 代码排版

奋斗吧
奋斗吧
擅长邻域:未填写

标签: 【每日一题】PTA - L3-019 代码排版

2023-06-29 18:23:29 174浏览

PTA - L3-019 代码排版

题目

PTA - L3-019 代码排版

解题思路

  • 大分天下,逐个治之
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class Main {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String code = scanner.nextLine();
        scanner.close();
        code = indentCode(code);
        System.out.println(code);
    }

    private interface Code {
        default String spaceFitCount(int count) {
            if (count == 0) {
                return "";
            }
            StringBuilder sb = new StringBuilder();
            while (count-- > 0) {
                sb.append(' ');
            }
            return sb.toString();
        }
    }

    private static class CodeBlock implements Code {
        //  contains code blocks and code lines
        List<Code> codes = new ArrayList<>();
        //  header code block start with the $spaceCount count of space
        int spaceCount;
        //  code block 's header line, no over with the char of "{"
        String codeHeader;
        //  parent
        CodeBlock parent;

        public CodeBlock(CodeBlock parent, String codeHeader) {
            this.parent = parent;
            if (parent != null) {
                this.spaceCount = parent.spaceCount + 2;
            } else {
                this.spaceCount = 0;
            }
            this.codeHeader = codeHeader;
        }

        public void addCode(Code code) {
            this.codes.add(code);
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            String spaceStr = spaceFitCount(spaceCount);
            if (parent == null) {
                sb.append(codeHeader).append("\r\n").append("{\r\n");
            } else {
                sb.append(spaceStr).append(codeHeader).append(" {\r\n");
            }
            for (Code code : codes) {
                sb.append(code.toString());
            }
            sb.append(spaceStr).append("}\r\n");
            return sb.toString();
        }
    }

    private static class CodeLine implements Code {
        //  code line parent
        CodeBlock parent;
        String strCodeLine;
        int spaceCount;


        public CodeLine(CodeBlock parent, String strCodeLine) {
            this.parent = parent;
            this.strCodeLine = strCodeLine;
            this.spaceCount = parent.spaceCount + 2;
        }

        @Override
        public String toString() {
            return spaceFitCount(spaceCount) + strCodeLine + "\r\n";
        }
    }

    private static String indentCode(String code) {
        Matcher matcher = Pattern.compile("int\\s+main\\s*\\(\\s*\\)").matcher(code);
        String formatCode = "";
        if (matcher.find()) {
            String strMain = matcher.group();

            //  main code block
            matcher = Pattern.compile("\\{.*}").matcher(code);
            if (matcher.find()) {
                String strMainCodeBlack = matcher.group();
                strMainCodeBlack = strMainCodeBlack.substring(1, strMainCodeBlack.length() - 1);

                CodeBlock mainCodeBlock = new CodeBlock(null, strMain);

                parseCodeBlack(strMainCodeBlack, mainCodeBlock);

                formatCode = mainCodeBlock.toString();
            }
        }
        return formatCode;
    }

    /**
     * parse strCodeBlack into codeBlock
     */
    private static void parseCodeBlack(String strCodeBlack, CodeBlock codeBlock) {
        String local = parseWhile(strCodeBlack, codeBlock);
        if (!strCodeBlack.equals(local)) {
            parseCodeBlack(local, codeBlock);
            return;
        }
        local = parseFor(strCodeBlack, codeBlock);
        if (!strCodeBlack.equals(local)) {
            parseCodeBlack(local, codeBlock);
            return;
        }
        local = parseIf(strCodeBlack, codeBlock);
        if (!strCodeBlack.equals(local)) {
            parseCodeBlack(local, codeBlock);
            return;
        }
        local = parseUsual(strCodeBlack, codeBlock);
        if (!strCodeBlack.equals(local)) {
            parseCodeBlack(local, codeBlock);
        }
    }


    private static final Pattern scanfPat = Pattern.compile("^\\s*scanf\\(\\s*?\".*?\"\\s*?,.*?\\);");
    private static final Pattern printfPat = Pattern.compile("^\\s*printf\\(\\s*?\".*?\"\\s*?,.*?\\);");
    private static final Pattern varPat = Pattern.compile("^.*?;");

    private static String parseUsual(String strCodeBlack, CodeBlock codeBlock) {
        Matcher matcher = scanfPat.matcher(strCodeBlack);
        if (!matcher.find()) { // scanf("xxx", d, a);
            matcher = printfPat.matcher(strCodeBlack);
            if (!matcher.find()) {
                //  variable define;
                matcher = varPat.matcher(strCodeBlack);
                if (!matcher.find()) {
                    return strCodeBlack;
                }
            }
        }
        int end = matcher.end();
        String strCodeLine = strCodeBlack.substring(0, end).trim();
        codeBlock.addCode(new CodeLine(codeBlock, strCodeLine));

        strCodeBlack = strCodeBlack.substring(end);
        return strCodeBlack;
    }

    private static final Pattern ifPat = Pattern.compile("^\\s*if\\s*\\(?");

    private static String parseIf(String strCodeBlack, CodeBlock codeBlock) {
        // if ( (a == b) && ( a == 'c' ) ) {
        Matcher matcher = ifPat.matcher(strCodeBlack);
        if (matcher.find()) { // if(
            //  strCodeBlack = " if ( (a == b) && ( a == 'c' ) ) ";
            Object[] objects = doParseCondition(strCodeBlack, codeBlock);
            strCodeBlack = (String) objects[0];
            codeBlock = (CodeBlock) objects[1]; // if

            matcher = bracketPat.matcher(strCodeBlack);
            if (matcher.find()) { // if (...) { : has '{'
                int start = matcher.end();
                int count = 0, end = start;
                for (int i = 0; i < strCodeBlack.length(); i++) {
                    char ch = strCodeBlack.charAt(i);
                    if (ch == '{') {
                        count++;
                        continue;
                    }
                    if (ch == '}') {
                        count--;
                        if (count == 0) {
                            end = i;
                            break;
                        }
                    }
                }
                end++;
                parseCodeBlack(strCodeBlack.substring(start, end - 1), codeBlock);
                strCodeBlack = strCodeBlack.substring(end);
                strCodeBlack = parseElse(strCodeBlack, codeBlock.parent);
                return strCodeBlack;
            }
            // if (...)
            strCodeBlack = parseSingle(strCodeBlack, codeBlock);
            strCodeBlack = parseElse(strCodeBlack, codeBlock.parent);
            return strCodeBlack;
        }
        return strCodeBlack;
    }

    private static final Pattern elsePat = Pattern.compile("^\\s*else");

    private static String parseElse(String strCodeBlack, CodeBlock codeBlock) {
        Matcher matcher = elsePat.matcher(strCodeBlack);
        if (!matcher.find()) {
            return strCodeBlack;
        }
        CodeBlock elseCodeBlack = new CodeBlock(codeBlock, "else");
        codeBlock.addCode(elseCodeBlack);
        codeBlock = elseCodeBlack;

        strCodeBlack = strCodeBlack.substring(matcher.end());

        matcher = bracketPat.matcher(strCodeBlack);
        if (matcher.find()) { // else { : has '{'
            int start = matcher.end();
            int count = 0, end = start;
            for (int i = 0; i < strCodeBlack.length(); i++) {
                char ch = strCodeBlack.charAt(i);
                if (ch == '{') {
                    count++;
                    continue;
                }
                if (ch == '}') {
                    count--;
                    if (count == 0) {
                        end = i;
                        break;
                    }
                }
            }
            end++;
            parseCodeBlack(strCodeBlack.substring(start, end - 1), codeBlock);
            return strCodeBlack.substring(end);
        }
        // else
        strCodeBlack = parseSingle(strCodeBlack, codeBlock);
        return strCodeBlack;
    }

    private static final Pattern whilePat = Pattern.compile("^\\s*while\\s*\\(?");

    private static String parseWhile(String strCodeBlack, CodeBlock codeBlock) {
        Matcher matcher = whilePat.matcher(strCodeBlack);
        return doParseWhileAndFor(matcher, strCodeBlack, codeBlock);
    }

    private static final Pattern bracketPat = Pattern.compile("^\\s*\\{");

    private static String doParseWhileAndFor(Matcher matcher, String strCodeBlack, CodeBlock codeBlock) {
        if (!matcher.find()) { // while/for(
            return strCodeBlack;
        }
        Object[] objects = doParseCondition(strCodeBlack, codeBlock);
        strCodeBlack = (String) objects[0];
        codeBlock = (CodeBlock) objects[1];

        matcher = bracketPat.matcher(strCodeBlack);
        if (matcher.find()) { // while/for (...) { : has '{'
            int start = matcher.end();
            int count = 0, end = start;
            for (int i = 0; i < strCodeBlack.length(); i++) {
                char ch = strCodeBlack.charAt(i);
                if (ch == '{') {
                    count++;
                    continue;
                }
                if (ch == '}') {
                    count--;
                    if (count == 0) {
                        end = i;
                        break;
                    }
                }
            }
            end++;
            parseCodeBlack(strCodeBlack.substring(start, end - 1), codeBlock);
            return strCodeBlack.substring(end);
        }
        //  while/for ()
        strCodeBlack = parseSingle(strCodeBlack, codeBlock);
        return strCodeBlack;
    }

    private static final Pattern forPat = Pattern.compile("^\\s*for\\s*\\(?");

    private static String parseFor(String strCodeBlack, CodeBlock codeBlock) {
        Matcher matcher = forPat.matcher(strCodeBlack);
        return doParseWhileAndFor(matcher, strCodeBlack, codeBlock);
    }

    private static String parseSingle(String strCodeBlack, CodeBlock codeBlock) {
        String tmpStrCodeBlack = parseWhile(strCodeBlack, codeBlock);
        if (!tmpStrCodeBlack.equals(strCodeBlack)) {
            return tmpStrCodeBlack;
        }
        tmpStrCodeBlack = parseFor(strCodeBlack, codeBlock);
        if (!tmpStrCodeBlack.equals(strCodeBlack)) {
            return tmpStrCodeBlack;
        }
        tmpStrCodeBlack = parseIf(strCodeBlack, codeBlock);
        if (!tmpStrCodeBlack.equals(strCodeBlack)) {
            return tmpStrCodeBlack;
        }
        tmpStrCodeBlack = parseUsual(strCodeBlack, codeBlock);
        return tmpStrCodeBlack;
    }

    private static Object[] doParseCondition(String strCodeBlack, CodeBlock codeBlock) {
        int end = 0, count = 0;
        for (int i = 0; i < strCodeBlack.length(); i++) {
            char ch = strCodeBlack.charAt(i);
            if (ch == '(') {
                count++;
                continue;
            }
            if (ch == ')') {
                count--;
                if (count == 0) {
                    end = i;
                    break;
                }
            }
        }
        end++;
        String strCodeLine = strCodeBlack.substring(0, end).trim();
//        System.out.println(strCodeLine);

        CodeBlock conditionCodeBlock = new CodeBlock(codeBlock, strCodeLine);
        codeBlock.addCode(conditionCodeBlock);

        strCodeBlack = strCodeBlack.substring(end);

        return new Object[]{strCodeBlack, conditionCodeBlock};
    }

}

优化

好博客就要一起分享哦!分享海报

此处可发布评论

评论(0展开评论

暂无评论,快来写一下吧

展开评论

您可能感兴趣的博客

客服QQ 1913284695