续上一篇文章,用栈来实现:按照用户输入的rule,经过并、交、差运算后,输出字符串结果。

来源:互联网 发布:windows平板不好用 编辑:程序博客网 时间:2024/03/29 07:40

废话不说了,

文件:

A{1,2,3,4,5,6}
B{7,4,5,6,8}
C{2,3,12,14,4,11}

 

测试时输入到控制台的字符串为:

C+B-(A*(C-A))+B

 

结果:

2 3 12 14 4 11 7 8 1 5 6

 

自己算了一下,是正确的!

 

代码如下,注释也写的蛮多的:

  1. /**
  2.  * 从事先写好的Input.txt文件中读取数, 
  3.  *  Input.txt 内容 
  4.  *  A{13,2,1,20,30,50} 
  5.  *  B{1,2,34,5,6} 
  6.  *  C{2,3,12,23,14,11} 
  7.  *  用户在键盘随意敲入...例如((A*B))+B-C,((C+B)*A)-B期中+,*,-,分别代表集合的并交差运算,控制台打印输出。
  8.  */
  9. package com.lim.test;
  10. import java.io.BufferedReader;
  11. import java.io.FileInputStream;
  12. import java.io.IOException;
  13. import java.io.InputStreamReader;
  14. import java.lang.reflect.InvocationTargetException;
  15. import java.lang.reflect.Method;
  16. import java.util.ArrayList;
  17. import java.util.List;
  18. import java.util.Stack;
  19. /**
  20.  * @author bzwm
  21.  * 
  22.  */
  23. public class EditorStringV2 {
  24.     // 保存住集合A中的数据
  25.     private Type typeA = null;
  26.     // 保存住集合B中的数据
  27.     private Type typeB = null;
  28.     // 保存住集合C中的数据
  29.     private Type typeC = null;
  30.     private Stack stack = new Stack();
  31.     public EditorStringV2(String path) {
  32.         readFile(path);
  33.     }
  34.     /**
  35.      * 读入指定的文件
  36.      * 
  37.      * @param path
  38.      */
  39.     private void readFile(String path) {
  40.         BufferedReader reader = null;
  41.         try {
  42.             reader = new BufferedReader(new InputStreamReader(
  43.                     new FileInputStream(path)));
  44.             String str = null;
  45.             // 保存已经写好的文件中A,B,C的集合
  46.             while ((str = reader.readLine()) != null) {
  47.                 // 保存集合A
  48.                 if (str.substring(0, 1).equals("A")) {
  49.                     typeA = new Type(str);
  50.                 }
  51.                 // 保存集合B
  52.                 else if (str.substring(0, 1).equals("B")) {
  53.                     typeB = new Type(str);
  54.                 }
  55.                 // 保存集合C
  56.                 else if (str.substring(0, 1).equals("C")) {
  57.                     typeC = new Type(str);
  58.                 } else {
  59.                     System.out.println("no such type!");
  60.                     return;
  61.                 }
  62.             }
  63.         } catch (Exception e) {
  64.             e.printStackTrace();
  65.             return;
  66.         }
  67.     }
  68.     /**
  69.      * 处理并、交、差操作,显示结果
  70.      * 
  71.      * @param rule
  72.      *            例:C-((C+B)-A)*B
  73.      * @throws InvocationTargetException
  74.      * @throws IllegalAccessException
  75.      * @throws NoSuchMethodException
  76.      * @throws IllegalArgumentException
  77.      * @throws SecurityException
  78.      */
  79.     public Stack displayResult(Stack orgStack) throws SecurityException,
  80.             IllegalArgumentException, NoSuchMethodException,
  81.             IllegalAccessException, InvocationTargetException {
  82.         // 左括号"("的计数器
  83.         int leftBracket = 0;
  84.         // 是否存在操作符标志符
  85.         boolean hasOpe = false;
  86.         // 输入的rule的长度
  87.         int length = orgStack.size();
  88.         Object obj = null;
  89.         if (length < 3) {
  90.             System.out.println("input rule is illegal.");
  91.             return null;
  92.         } else {
  93.             for (int i = 0; i < length; i++) {
  94.                 // 截取rule的每个字符
  95.                 obj = orgStack.pop();
  96.                 // 如果是左括号,则leftBracket加1
  97.                 if (isLeftBracket(obj)) {
  98.                     leftBracket += 1;
  99.                     stack.push(obj);
  100.                     continue;
  101.                 }
  102.                 // 如果是操作符,则将操作符标志符置为true
  103.                 if (isOperator(obj)) {
  104.                     hasOpe = true;
  105.                     stack.push(obj);
  106.                     continue;
  107.                 }
  108.                 // 如果不是左括号和操作符则入栈
  109.                 stack.push(obj);
  110.                 // 如果左括号存在,且本次字符为右括号
  111.                 if (leftBracket > 0 && isRightBracket(obj)) {
  112.                     // 将右括号弹出栈
  113.                     stack.pop();
  114.                     // 将形如typeA.bing(typeB)的方法调用的参数标志弹出
  115.                     Type arg = (Type) stack.pop();
  116.                     // 将形如typeA.bing(typeB)的方法调用的操作符标志弹出:+/bing */jiao -/cha
  117.                     String ope = stack.pop().toString();
  118.                     // 将形如typeA.bing(typeB)的方法调用的主调对象标志弹出
  119.                     Type invokeObj = (Type) stack.pop();
  120.                     // 通过对象工厂,构造出Type对象,进行并、交、差操作,返回得到的新Type对象
  121.                     Type typeTmp = execute(invokeObj, ope, arg);
  122.                     // 将左括号弹出栈
  123.                     stack.pop();
  124.                     // 左括号计数器减1
  125.                     leftBracket -= 1;
  126.                     // 栈中加入临时的Type对象标志T,T代表本次操作后得到的新集合
  127.                     stack.push(typeTmp);
  128.                     // 当栈中还有运算时,进行递归
  129.                     if (stack.size() > 2) {
  130.                         Stack tmpStack = new Stack();
  131.                         while (stack.size() > 0) {
  132.                             tmpStack.push(stack.pop());
  133.                         }
  134.                         stack = displayResult(tmpStack);
  135.                     }
  136.                     continue;
  137.                 }
  138.                 // 如果1.栈中还没有左括号 2.栈有操作符 3.本次字符是集合标志A、B、C
  139.                 // 则进行并、交、差操作
  140.                 if (leftBracket == 0 && hasOpe && isType(obj)) {
  141.                     // 将形如typeA.bing(typeB)的方法调用的参数标志弹出
  142.                     Type arg = (Type) stack.pop();
  143.                     // 将形如typeA.bing(typeB)的方法调用的操作符标志弹出:+/bing */jiao -/cha
  144.                     String ope = stack.pop().toString();
  145.                     // 将形如typeA.bing(typeB)的方法调用的主调对象标志弹出
  146.                     Type invokeObj = (Type) stack.pop();
  147.                     // 通过对象工厂,构造出Type对象,进行并、交、差操作,返回得到的新Type对象
  148.                     Type typeTmp = execute(invokeObj, ope, arg);
  149.                     // 栈中加入临时的Type对象标志T,T代表本次操作后得到的新集合
  150.                     stack.push(typeTmp);
  151.                     // 将操作符标志符置为false
  152.                     hasOpe = false;
  153.                     // 当栈中还有运算时,进行递归
  154.                     if (stack.size() > 2) {
  155.                         Stack tmpStack = new Stack();
  156.                         while (stack.size() > 0) {
  157.                             tmpStack.push(stack.pop());
  158.                         }
  159.                         stack = displayResult(tmpStack);
  160.                     }
  161.                     continue;
  162.                 }
  163.             }
  164.             // 循环结束,得到最后结果
  165.             return stack;
  166.         }
  167.     }
  168.     /**
  169.      * 判断对象o是否为Type的实例
  170.      * 
  171.      * @param o
  172.      * @return
  173.      */
  174.     private boolean isType(Object o) {
  175.         return o instanceof Type;
  176.     }
  177.     /**
  178.      * 判断对象o是否为操作符*,+,-
  179.      * 
  180.      * @param o
  181.      * @return
  182.      */
  183.     private boolean isOperator(Object o) {
  184.         return !isType(o) && ((String) o).matches("[+//*-]");
  185.     }
  186.     /**
  187.      * 判断对象o是否左括号"("
  188.      * 
  189.      * @param o
  190.      * @return
  191.      */
  192.     private boolean isLeftBracket(Object o) {
  193.         return !isType(o) && ((String) o).equals("(");
  194.     }
  195.     /**
  196.      * 判断对象o是否右括号")"
  197.      * 
  198.      * @param o
  199.      * @return
  200.      */
  201.     private boolean isRightBracket(Object o) {
  202.         return !isType(o) && ((String) o).equals(")");
  203.     }
  204.     /**
  205.      * 利用反射机制,根据ope的不同,调用不同的方法
  206.      * 
  207.      * @param obj
  208.      * @param arg
  209.      * @param ope
  210.      * @return
  211.      * @throws SecurityException
  212.      * @throws NoSuchMethodException
  213.      * @throws IllegalArgumentException
  214.      * @throws IllegalAccessException
  215.      * @throws InvocationTargetException
  216.      */
  217.     private Type execute(Type obj, String ope, Type arg)
  218.             throws SecurityException, NoSuchMethodException,
  219.             IllegalArgumentException, IllegalAccessException,
  220.             InvocationTargetException {
  221.         Class c = obj.getClass();
  222.         Class[] args = new Class[1];
  223.         args[0] = arg.getClass();
  224.         Method m = null;
  225.         // 如果操作符为"+",则执行bing方法
  226.         if (ope.equals("+")) {
  227.             m = c.getMethod("bing", args);
  228.         }
  229.         // 如果操作符为"*",则执行jiao方法
  230.         else if (ope.equals("*")) {
  231.             m = c.getMethod("jiao", args);
  232.         }
  233.         // 如果操作符为"-",则执行cha方法
  234.         else if (ope.equals("-")) {
  235.             m = c.getMethod("cha", args);
  236.         } else {
  237.             System.out.println("NoSuchMethod");
  238.             return null;
  239.         }
  240.         return (Type) m.invoke(obj, new Object[] { arg });
  241.     }
  242.     /**
  243.      * 读入用户输入的匹配规则 如:((C+B)*A)-B
  244.      * 
  245.      * @return
  246.      */
  247.     private Stack readInput() {
  248.         Stack ret = new Stack();
  249.         String str = null;
  250.         String o = null;
  251.         BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  252.         try {
  253.             str = br.readLine();
  254.         } catch (IOException e) {
  255.             e.printStackTrace();
  256.             return null;
  257.         }
  258.         for (int i = str.length(); i > 0; i--) {
  259.             o = str.substring(i - 1, i);
  260.             // 当遇到A,B,C时,生成Type对象存入栈中
  261.             if (o.matches("[ABC]")) {
  262.                 ret.push(typeFactory(o));
  263.                 continue;
  264.             }
  265.             ret.push(o);
  266.         }
  267.         return ret;
  268.     }
  269.     /**
  270.      * 构造工厂 根据传入的type构造Type对象 保存住原集合
  271.      * 
  272.      * @param type
  273.      * @return
  274.      */
  275.     private Type typeFactory(String type) {
  276.         if (type.equals("A")) {
  277.             return new Type(typeA.getArray());
  278.         } else if (type.equals("B")) {
  279.             return new Type(typeB.getArray());
  280.         } else if (type.equals("C")) {
  281.             return new Type(typeC.getArray());
  282.         } else {
  283.             return null;
  284.         }
  285.     }
  286.     /**
  287.      * 把如{13,2,1,20,30,50}的集合抽象成一个类,提供并、交、差操作
  288.      * 
  289.      * @author bzwm
  290.      * 
  291.      */
  292.     class Type {
  293.         // 保存数据集合的List
  294.         private List array = new ArrayList();
  295.         public Type(String srt) {
  296.             this.array = createList(srt);
  297.         }
  298.         public Type(List list) {
  299.             this.array.addAll(list);
  300.         }
  301.         public List getArray() {
  302.             return this.array;
  303.         }
  304.         /**
  305.          * 并操作
  306.          * 
  307.          * @param arg
  308.          * @return
  309.          */
  310.         public Type bing(Type arg) {
  311.             // 是否加入到集合中的标志
  312.             boolean add = true;
  313.             // 取出传入的Type对象的List
  314.             List list = arg.getArray();
  315.             // 遍历传入的Type对象的List
  316.             for (int i = 0; i < list.size(); i++) {
  317.                 add = true;
  318.                 // 与array里的值一一进行比较,如果全都不等,则加入到原array中,否则不加入
  319.                 for (int j = 0; j < array.size(); j++) {
  320.                     if (((Integer) list.get(i)).intValue() == ((Integer) array
  321.                             .get(j)).intValue()) {
  322.                         add = false;
  323.                     }
  324.                 }
  325.                 if (add) {
  326.                     array.add(list.get(i));
  327.                 }
  328.             }
  329.             // 返回新的Type对象
  330.             return new Type(array);
  331.         }
  332.         /**
  333.          * 交操作
  334.          * 
  335.          * @param arg
  336.          * @return
  337.          */
  338.         public Type jiao(Type arg) {
  339.             // 是否加入到集合中的标志
  340.             boolean add = false;
  341.             // 存放交集数据的List
  342.             List ret = new ArrayList();
  343.             // 取出传入的Type对象的List
  344.             List list = arg.getArray();
  345.             // 遍历传入的Type对象的List
  346.             for (int i = 0; i < list.size(); i++) {
  347.                 add = false;
  348.                 // 与array里的值一一进行比较,如果有相等的,则加入到ret中,否则不加入
  349.                 for (int j = 0; j < array.size(); j++) {
  350.                     if (((Integer) list.get(i)).intValue() == ((Integer) array
  351.                             .get(j)).intValue()) {
  352.                         add = true;
  353.                     }
  354.                 }
  355.                 if (add) {
  356.                     ret.add(list.get(i));
  357.                 }
  358.             }
  359.             // 返回新的Type对象
  360.             return new Type(ret);
  361.         }
  362.         /**
  363.          * 差操作
  364.          * 
  365.          * @param arg
  366.          * @return
  367.          */
  368.         public Type cha(Type arg) {
  369.             // 是否加入到集合中的标志
  370.             boolean add = true;
  371.             // 存放交集数据的List
  372.             List list = arg.getArray();
  373.             // 遍历传入的Type对象的List
  374.             for (int i = 0; i < list.size(); i++) {
  375.                 add = true;
  376.                 // 与array里的值一一进行比较,如果有相等的,则从原array中将其删除,如果全都不等,则加入到原array中
  377.                 for (int j = 0; j < array.size(); j++) {
  378.                     if (((Integer) list.get(i)).intValue() == ((Integer) array
  379.                             .get(j)).intValue()) {
  380.                         add = false;
  381.                         // 删除相等的数据
  382.                         array.remove(j);
  383.                     }
  384.                 }
  385.                 if (add) {
  386.                     array.add(list.get(i));
  387.                 }
  388.             }
  389.             // 返回新的Type对象
  390.             return new Type(array);
  391.         }
  392.         /**
  393.          * 解析字符串,将数字加入到List中
  394.          * 
  395.          * @param str
  396.          * @return
  397.          */
  398.         private List createList(String str) {
  399.             // 将字符串解析成字符串数组A{13,2,1,20,30,50}-->new String[]{13,2,1,20,30,50}
  400.             String s[] = str.replaceAll(str.substring(0, 1), "").replace("{",
  401.                     "").replace("}""").split(",");
  402.             List list = new ArrayList();
  403.             for (int i = 0; i < s.length; i++) {
  404.                 list.add(new Integer(s[i]));
  405.             }
  406.             return list;
  407.         }
  408.     }
  409.     /**
  410.      * 测试程序
  411.      * 
  412.      * @param args
  413.      * @throws InvocationTargetException
  414.      * @throws IllegalAccessException
  415.      * @throws NoSuchMethodException
  416.      * @throws IllegalArgumentException
  417.      * @throws SecurityException
  418.      */
  419.     public static void main(String args[]) throws SecurityException,
  420.             IllegalArgumentException, NoSuchMethodException,
  421.             IllegalAccessException, InvocationTargetException {
  422.         EditorStringV2 es = new EditorStringV2("input.txt");
  423.         Stack s = es.readInput();
  424.         Stack result = es.displayResult(s);// ((C+B)*A)-B
  425.         List list = ((Type) result.pop()).getArray();
  426.         System.out.println("操作运算后结果为:");
  427.         for (int i = 0; i < list.size(); i++)
  428.             System.out.print(list.get(i) + " ");
  429.     }
  430. }