user2577854
user2577854

Reputation:

Splitting string algorithm in Java

I'm trying to make the following algorithm work. What I want to do is split the given string into substrings consisting of either a series of numbers or an operator.

So for this string = "22+2", I would get an array in which [0]="22" [1]="+" and [2]="2".

This is what I have so far, but I get an index out of bounds exception:

public static void main(String[] args) {
    String string = "114+034556-2";
    int k,a,j;
    k=0;a=0;j=0;
    String[] subStrings= new String[string.length()];

    while(k<string.length()){
        a=k;
        while(((int)string.charAt(k))<=57&&((int)string.charAt(k))>=48){
            k++;}
        subStrings[j]=String.valueOf(string.subSequence(a,k-1)); //exception here

        j++;
        subStrings[j]=String.valueOf(string.charAt(k));
        j++;

   }}

I would rather be told what's wrong with my reasoning than be offered an alternative, but of course I will appreciate any kind of help.

Upvotes: 1

Views: 628

Answers (5)

Zo the Relativist
Zo the Relativist

Reputation: 117

I'm deliberately not answering this question directly, because it looks like you're trying to figure out a solution yourself. I'm also assuming that you're purposefully not using the split or the indexOf functions, which would make this pretty trivial.

A few things I've noticed:

  1. If your input string is long, you'd probably be better off working with a char array and stringbuilder, so you can avoid memory problems arising from immutable strings
  2. Have you tried catching the exception, or printing out what the value of k is that causes your index out of bounds problem?
  3. Have you thought through what happens when your string terminates? For instance, have you run this through a debugger when the input string is "454" or something similarly trivial?

Upvotes: 2

budaancamanyak
budaancamanyak

Reputation: 51

String input="22+2-3*212/21+23";
     String number="";
     String op="";
     List<String> numbers=new ArrayList<String>();
     List<String> operators=new ArrayList<String>();
     for(int i=0;i<input.length();i++){
         char c=input.charAt(i);
         if(i==input.length()-1){
             number+=String.valueOf(c);
             numbers.add(number);
         }else if(Character.isDigit(c)){
             number+=String.valueOf(c);
         }else{
              if(c=='+' || c=='-' || c=='*' ||c=='/'){
             op=String.valueOf(c);
             operators.add(op);
             numbers.add(number);
             op="";
             number="";
             }
         }
     }
     for(String x:numbers){
         System.out.println("number="+x+",");
     }
     for(String x:operators){
         System.out.println("operators="+x+",");
     }

this will be the output number=22,number=2,number=3,number=212,number=21,number=23,operator=+,operator=-,operator=*,operator=/,operator=+,

Upvotes: 0

If your critera is simply "Anything that is not a number", then you can use some simple regex stuff if you dont mind working with parallel arrays -

String[] operands = string.split("\\D");\\split around anything that is NOT a number
char[] operators = string.replaceAll("\\d", "").toCharArray();\\replace all numbers with "" and turn into char array.

Upvotes: 0

rcreswick
rcreswick

Reputation: 16823

If you're interested in the general problem of parsing, then I'd recommend thinking about it on a character-by-character level, and moving through a finite state machine with each new character. (Often you'll need a terminator character that cannot occur in the input--such as the \0 in C strings--but we can get around that.).

In this case, you might have the following states:

  1. initial state
  2. just parsed a number.
  3. just parsed an operator.

The characters determine the transitions from state to state:

  • You start in state 1.
  • Numbers transition into state 2.
  • Operators transition into state 3.

The current state can be tracked with something like an enum, changing the state after each character is consumed.

With that setup, then you just need to loop over the input string and switch on the current state.

// this is pseudocode -- does not compile.
List<String> parse(String inputString) {
    State state = INIT_STATE;
    String curr = "";
    List<String> subStrs = new ArrayList<String>();
    for(Char c : inputString) {
      State next;
      if (isAnumber(c)) {
        next = JUST_NUM;
      } else {
        next = JUST_OP;
      }

      if (state == next) {
        // no state change, just add to accumulator:
        acc = acc + c;
      } else {
        // state change, so save and reset the accumulator:
        subStrs.add(acc);
        acc = "";
      }
      // update the state
      state = next;
    }
    return subStrs;
}

With a structure like that, you can more easily add new features / constructs by adding new states and updating the behavior depending on the current state and incoming character. For example, you could add a check to throw errors if letters appear in the string (and include offset locations, if you wanted to track that).

Upvotes: 0

Reimeus
Reimeus

Reputation: 159754

You could use a regular expression to split the numbers from the operators using lookahead and lookbehind assertions

String equation = "22+2";
String[] tmp = equation.split("(?=[+\\-/])|(?<=[+\\-/])");
System.out.println(Arrays.toString(tmp));

Upvotes: 1

Related Questions