Shorter solution to if,else if,else if

2019-02-14 11:51发布

I'm looking for a way to shorten this code up and avoid repeating code and if statements. What I'm doing is creating a calculator that searches strings for operators "* / + - " and executes them accordingly. Any ideas?

if(exp.charAt(i)=='*')
        {
            newResult=Integer.parseInt(exp.substring(0, i)) * Integer.parseInt(exp.substring(i+1, exp.length()));
            primeResult = newResult;
            System.out.println(primeResult);
        } 
        else if(exp.charAt(i)=='/')
        {
            newResult=Integer.parseInt(exp.substring(0, i)) / Integer.parseInt(exp.substring(i+1, exp.length()));
            primeResult = newResult;
            System.out.println(primeResult);
        } 
        else if(exp.charAt(i)=='+')
        {
            newResult=Integer.parseInt(exp.substring(0, i)) + Integer.parseInt(exp.substring(i+1, exp.length()));
            primeResult = newResult;
            System.out.println(primeResult);
        } 
        else if(exp.charAt(i)=='-')
        {
            newResult=Integer.parseInt(exp.substring(0, i)) - Integer.parseInt(exp.substring(i+1, exp.length()));
            primeResult = newResult;
            System.out.println(primeResult);
        } 

Also, is there a solution to accept a string with more than 2 operands? i.e. 5 + 10 * 2 / 3

6条回答
\"骚年 ilove
2楼-- · 2019-02-14 12:07

Here's a snippet:

public static void main(String[] args) {

        float primeResult;
        String exp = "4-2";
        int i = 1;
        ScriptEngineManager mgr = new ScriptEngineManager();
        ScriptEngine engine = mgr.getEngineByName("JavaScript");

        char[] myVar = new char[] { '*', '/', '-', '+' };

        for (int myVarCtr = 0; myVarCtr < myVar.length; myVarCtr++) {

            if (exp.charAt(i) == myVar[myVarCtr]) {

                try {
                    primeResult = Float.parseFloat(engine.eval(
                            (Integer.parseInt(exp.substring(0, i)))
                                    + Character.toString(myVar[myVarCtr])
                                    + (Integer.parseInt(exp.substring(i + 1,
                                            exp.length())))).toString());
                    System.out.println(primeResult);
                } catch (ScriptException e) {
                    e.printStackTrace();
                }

            }

        }
    }
查看更多
祖国的老花朵
3楼-- · 2019-02-14 12:20

You could write an AbstractCalculationOperation class with execute method, with Add, Subtract, etc extending it.

Then, just parse leftHand, rightHand, and calculationOperation and run calculationOperation.execute( rightHand, leftHand ).

    public interface CalculationOperation {
        double calculate ( double lh, double rh );
        long calculate ( long lh, long rh );
    }

    public class Add implements CalculationOperation {
        public static final CalculationOperation INSTANCE = new Add();
        public double calculate ( double rh, double lh ) { return lh + rh; }
        public long calculate ( long rh, long lh ) { return lh + rh; }
    }

And then:

    int lh = exp.substring(0, i);
    int rh = exp.substring(i+1);
    CalculationOperation op;
    switch( exp.charAt(i) ) {
        case '*': op = Multiply.INSTANCE; break;
        case '/': op = Divide.INSTANCE; break;
        case '+': op = Add.INSTANCE; break;
        case '-': op = Subtract.INSTANCE; break;
    }
    newResult = op.calculate( rh, lh );
    primeResult = newResult;
    System.out.println(primeResult);

Alternate enum variant:

   public enum Calculation {
      ADD('+') {
         public int calculate( int lhs, int rhs ) { return lhs + rhs; }
         public long calculate( long lhs, long rhs ) { return lhs + rhs; }
         public float calculate( float lhs, float rhs ) { return lhs + rhs; }
         public double calculate( double lhs, double rhs ) { return lhs + rhs; }
      },
      SUBTRACT('-') {
         public int calculate( int lhs, int rhs ) { return lhs - rhs; }
         public long calculate( long lhs, long rhs ) { return lhs - rhs; }
         public float calculate( float lhs, float rhs ) { return lhs - rhs; }
         public double calculate( double lhs, double rhs ) { return lhs - rhs; }
      },
      MULTIPLY('*') {
         public int calculate( int lhs, int rhs ) { return lhs * rhs; }
         public long calculate( long lhs, long rhs ) { return lhs * rhs; }
         public float calculate( float lhs, float rhs ) { return lhs * rhs; }
         public double calculate( double lhs, double rhs ) { return lhs * rhs; }
      },
      DIVIDE('/') {
         public int calculate( int lhs, int rhs ) { return lhs / rhs; }
         public long calculate( long lhs, long rhs ) { return lhs / rhs; }
         public float calculate( float lhs, float rhs ) { return lhs / rhs; }
         public double calculate( double lhs, double rhs ) { return lhs / rhs; }
      };

      private final char textValue;
      Calculation ( char textValue )
      {
         this.textValue = textValue;
      }

      public abstract int calculate ( int lht, int rhs );
      public abstract long calculate ( long lht, long rhs );
      public abstract float calculate ( float lht, float rhs );
      public abstract double calculate ( double lht, double rhs );

      public static Calculation fromTextValue( char textValue ) {
         for( Calculation op : values() )
            if( op.textValue == textValue )
               return op;
         throw new IllegalArgumentException( "Unknown operation: " + textValue );
      }
   }

and then:

    int lh = exp.substring(0, i);
    int rh = exp.substring(i+1);
    Calculation op = Calculation.fromTextValue( exp.substring(i,1) );
    newResult = op.calculate( lh, rh );
    primeResult = newResult;
    System.out.println(primeResult);
查看更多
我只想做你的唯一
4楼-- · 2019-02-14 12:21

For changing the code you could use a switch statement and putting some of the redundant code before or after the switch.

int left = Integer.parseInt(exp.substring(0,i));
int right = Integer.parseInt(exp.substring(i+1,exp.length()));
switch(exp.charAt(i)){
    case '*':
        primeResult = left * right;
        break;
    case '/':
        ...
        break;
    case '+':
        ...
        break;
    case '-':
        ...
        break;
    default:
        ... // Error Handling.
}
System.out.println(primeResult);
查看更多
不美不萌又怎样
5楼-- · 2019-02-14 12:22

It's pretty simple how to avoid too much code repetition:

Integer op1= Integer.parseInt(exp.substring(0, i);
Integer op2=Integer.parseInt(exp.substring(i+1, exp.length()));
if(exp.charAt(i)=='*')  {
            newResult=op1 * op2;
} else 
....
primeResult = newResult;
System.out.println(primeResult);

But to do something more general, robust and useful, with arbitrary nesting levels, you should use some real parser. For example.

查看更多
ゆ 、 Hurt°
6楼-- · 2019-02-14 12:26

Shorten the code by grabbing the variables separately from doing the operation. This will not reduce your "if" statements, but it will drastically reduce the line numbers.

Don't do multiple variables until you understand trees... I've never worked with them personally, but I think "expression trees" are what you'll be after. (note: I just checked on google, yep, Expression Trees)

查看更多
beautiful°
7楼-- · 2019-02-14 12:30

There's no need of switch statements and complex hierrachies of classes.

In order to simplify and shorten your code and calculate simple and complex expressions (represented as String objects), you can use the Java's JavaScript API and it's ScriptEngine class, which basically simulates a JavaScript console.

import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;

public class MyClass{
    public static void main(String[] args) throws Exception {
        // create a script engine manager
        ScriptEngineManager factory = new ScriptEngineManager();
        // create a JavaScript engine
        ScriptEngine engine = factory.getEngineByName("JavaScript");
        // evaluate JavaScript code from String
        System.out.println(engine.eval("(5+10)*2/3"));
    }
}

This will output: 10.0

查看更多
登录 后发表回答