Stringindexoutofboundsexception in android

I am trying to create a calculator app.IN order to avoid duplication of operators i am checking if the previous character in the string is an operator.But i am getting stringindexoutofboundsexception when i type in the third character.

package com.example.calculatorproject;

import android.app.Activity;
import android.os.Bundle;
import android.text.InputType;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;

public class MainActivity extends Activity {
    EditText txtresult;
    ImageButton ib_backspace;
    String result="";
    char  value;
    Button btnc,btn1,btn2,btn3,btn4,btn5,btn6,btn7,btn8,btn9,btn0,btn_add,btn_sub,btn_multi,btn_divide,btn_decimal,btn_equal;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        txtresult=(EditText) findViewById(R.id.txtresult);
        ib_backspace=(ImageButton) findViewById(R.id.ib_backspace);
        txtresult.setInputType(InputType.TYPE_NULL);
        btnc=(Button) findViewById(R.id.btnC);
        btn1=(Button) findViewById(R.id.btn1);
        btn2=(Button) findViewById(R.id.btn2);
        btn3=(Button) findViewById(R.id.btn3);
        btn4=(Button) findViewById(R.id.btn4);
        btn5=(Button) findViewById(R.id.btn5);
        btn6=(Button) findViewById(R.id.btn6);
        btn7=(Button) findViewById(R.id.btn7);
        btn8=(Button) findViewById(R.id.btn8);
        btn9=(Button) findViewById(R.id.btn9);
        btn0=(Button) findViewById(R.id.btn0);
        btn_add=(Button) findViewById(R.id.btn_add);
        btn_sub=(Button) findViewById(R.id.btn_sub);
        btn_multi=(Button) findViewById(R.id.btn_multi);
        btn_divide=(Button) findViewById(R.id.btn_divide);
        btn_decimal=(Button) findViewById(R.id.btn_decimal);
        btn_equal=(Button) findViewById(R.id.btn_equal);

        ib_backspace.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                result=txtresult.getText().toString();
                if(result.length()!=0)
                {
                result = result.substring(0, result.length()-1);
                setresult();
                }


            }
        });
        btnc.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                result="";
                setresult();

            }
        });
        btn0.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                result+="0";
                setresult();

            }
        });
btn1.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                result+="1";
                setresult();

            }
        });
btn2.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        result+="2";
        setresult();

    }
});
btn3.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        result+="3";
        setresult();
    }
});
btn4.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        result+="4";
        setresult();
    }
});
btn5.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        result+="5";
        setresult();
    }
});
btn6.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        result+="6";
        setresult();
    }
});
btn7.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        result+="7";
        setresult();
    }
});
btn8.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        result+="8";
        setresult();

    }
});
btn9.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        result+="9";
        setresult();

    }
});
btn_add.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        value=result.substring(result.length()-1).charAt(result.length()-1);
        if((value=='+')||(value=='-')||(value=='*')||(value=='/')||(value=='.'))
        {
            result=(result.substring(0,result.length()-1))+"+";
            setresult();
        }
        else
        {
        result+="+";
        setresult();
        }

    }
});
btn_sub.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        value=result.substring(result.length()-1).charAt(result.length()-1);
        if((value=='+')||(value=='-')||(value=='*')||(value=='/')||(value=='.'))
        {
            result=result.substring(0,result.length()-1)+"-";
            setresult();
        }
        else
        {
        result+="-";
        setresult();
        }

    }
});
btn_divide.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        value=result.substring(result.length()-1).charAt(result.length()-1);
        if((value=='+')||(value=='-')||(value=='*')||(value=='/')||(value=='.'))
        {
            result=result.substring(0,result.length()-1)+"/";
            setresult();
        }
        else
        {
        result+="/";
        setresult();
        }

    }
});
btn_multi.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        value=result.substring(result.length()-1).charAt(result.length()-1);
        if((value=='+')||(value=='-')||(value=='*')||(value=='/')||(value=='.'))
        {
            result=result.substring(0,result.length()-1)+"*";
            setresult();
        }
        else
        {
        result+="*";
        setresult();
        }   
    }
});

btn_decimal.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        result+=".";
        setresult();    

    }
});

btn_equal.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub

    }
});


    }
    public void setresult()
    {
        txtresult.setText(result);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }



}

For eg if i type "9+5-*" as the expression the * should replace the - sign.But even when i type 9+5 there is a stringoutofboundsexception when i type +.Please help!!

The logcat

05-15 06:03:50.317: E/AndroidRuntime(1492): FATAL EXCEPTION: main  
05-15 06:03:50.317: E/AndroidRuntime(1492): Process: com.example.calculatorproject, PID: 1492  
05-15 06:03:50.317: E/AndroidRuntime(1492): java.lang.StringIndexOutOfBoundsException: length=1; index=2  
05-15 06:03:50.317: E/AndroidRuntime(1492):     at com.example.calculatorproject.MainActivity$14.onClick(MainActivity.java:175)  
05-15 06:03:50.317: E/AndroidRuntime(1492):     at android.view.View.performClick(View.java:4424)  
05-15 06:03:50.317: E/AndroidRuntime(1492):     at android.view.View$PerformClick.run(View.java:18383)  
05-15 06:03:50.317: E/AndroidRuntime(1492):     at android.os.Handler.handleCallback(Handler.java:733)  
05-15 06:03:50.317: E/AndroidRuntime(1492):     at android.os.Handler.dispatchMessage(Handler.java:95)  
05-15 06:03:50.317: E/AndroidRuntime(1492):     at android.os.Looper.loop(Looper.java:137)  
05-15 06:03:50.317: E/AndroidRuntime(1492):     at android.app.ActivityThread.main(ActivityThread.java:4998)  
05-15 06:03:50.317: E/AndroidRuntime(1492):     at java.lang.reflect.Method.invokeNative(Native Method)  
05-15 06:03:50.317: E/AndroidRuntime(1492):     at java.lang.reflect.Method.invoke(Method.java:515)  
05-15 06:03:50.317: E/AndroidRuntime(1492):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777)  
05-15 06:03:50.317: E/AndroidRuntime(1492):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593)  
05-15 06:03:50.317: E/AndroidRuntime(1492):     at dalvik.system.NativeStart.main(Native Method)  
Jon Skeet
people
quotationmark

This line is broken for any string with a length other than 1:

value = result.substring(result.length()-1).charAt(result.length()-1);

Consider different lengths:

  • 0 (result is an empty string): result.substring(result.length() - 1) will fail as you're calling result.substring(-1). Bang.
  • 1 (result is a single-character string): result.substring(0) returns a one-character string (equivalent to result) and then charAt(0) returns that single character
  • 2 or more: result.substring(result.length() - 1) returns a one-character string, and then you're calling charAt with a value more than 0. Bang.

If you're just trying to find the last character of the string, you want:

value = result.charAt(result.length() - 1);

There's no need for a substring call.

I'd also strongly urge you to consider using more local variables and fewer instance variables. Why is value an instance variable for example? Why is result an instance variable when you basically want to manipulate the text box contents?

people

See more on this question at Stackoverflow