0

Okay so I have this server that creates a randomly generated array, then tells the user to remove a number. However I added a section so that if the user selects a number that's NOT in the array then it tells them to select again... It successfully tells the user that's not in the array and to pick again and then it just allows me to enter numbers freely without continuing the program... here is my code and here is what I get as responses

    import java.util.Random;
    import java.util.Scanner;
    public class Server {
        public static boolean checked = false;
        public static int removed;
        public static int inserted;
        public static int index;
        public static int[] array =  new int[50];
        public static void generateArray(){
            Random random = new Random();
            for(int i=0; i<array.length; i++){
                int x = random.nextInt(101);
                if(x>0){
                    array[i]= x;}
                else{
                    i--;}
                for (int j=0; j < i; j++) {
                    if (array[i] == array[j]) {
                        i--;
                    }
                }

            }
            for(int i=0; i<array.length; i++){
                System.out.print(array[i] + " ");
            }
            System.out.println();
        }

        public static void insertRemove(){
            Scanner input = new Scanner(System.in);
            if(checked == false){
                System.out.println("Select a number to be removed.");
                checked = true;
            }
            removed = input.nextInt();
            Server.checkValid();
            if(checked == true){
                System.out.println("Select a new number to be inserted.");
                inserted = input.nextInt();
                System.out.println("Select an index for the number to be inserted at.");
                index = input.nextInt();
            }
        }
    public static void checkValid(){
        boolean repeat = false;
        loop:
        for(int i=0; i<array.length; i++){
            for(int j=0; j<array.length; j++){
            if(array[i] == removed){
                checked = true;
                Server.insertRemove();
            }
            else{
                System.out.println("That number isn't in the array.");
                checked = false;
                repeat = true;
                if(checked == false){
                    break loop;
                }
                else{}
            }
            }
        }
        if(repeat == true){
            Server.insertRemove();
        }
    }
}

Responses
It is also only checking the first number of the array, due to the else... break; but if i do a double loop using for(int j=0; j<array.length j++) then it prints That number isn't in the array. 50 times.

43 27 62 44 85 15 61 17 59 20 84 73 60 49 26 54 41 5 64 96 32 68 86 7 52 53 47 19 58 18 70 74 50 28 38 91 89 1 36 42 78 45 97 57 9 29 55 2 40 90 
Select a number to be removed.
0
That number isn't in the array.
Select a number to be removed.
43
43
43  // <----as you can see it's still allowing me to just type in 43
43

There is a main method that calls this...

public class Main {
    public static void main(String[] args){
        Server.generateArray();
        Server.insertRemove();
    }
}

Basically how can I fix this loop that is currently allowing me to insert numbers, so that if I insert something not in the array then something actually in the array then it will allow me to continue the normal program and ask me for a number to insert, index to be inserted at, etc.

Adamc23
  • 157
  • 1
  • 11
  • What is your question? – Dawood ibn Kareem Mar 03 '14 at 04:52
  • `break` only breaks out of one level of loop or switch. It is up to you to figure out if the loop was broken out of and do something about it (like breaking out of the next level) In your case do a test on checked after the inside loop before the end of the outside loop and if it is false break the outside loop as well. – Jerry Jeremiah Mar 03 '14 at 04:53
  • if I remove break it repeats That number isn't in the array. 50 times – Adamc23 Mar 03 '14 at 04:56
  • @JerryJeremiah okay so I did what you said and that fixes repeated "not in array" 50 times, but once I insert say 25 and 25 is in the array it just does nothing, although it doesn't terminate the program goes nowhere – Adamc23 Mar 03 '14 at 05:00

2 Answers2

3

There's a somewhat common beginner mistake in your 'contains' logic. It looks like this:

for(/* elements in array */){
    if(/* check one element */){
        // do contains action
    } else {
        // do not contains action
    }
}

It doesn't work because it only checks the first element in the array. The 'else' action needs to be after the loop. It needs to be done after checking the entire array.

(This bug is also why it repeats the 'not in the array' message when the break is removed, because it enters the else clause for every number that isn't the match.)

But more importantly your use of state to manage these two methods isn't good. You have a pattern that looks like this:

method1 calls method2
    if not method2 call method1
        method1 calls method2
            method2 completes normally
        ...also returns to method1
    ...also returns to method2
...also returns to method1

The messy logic of this has created a bug which is that your state variable checked never gets reset. It's possible that sticking a checked = false; statement at the end would correct the bug but here I'd recommend a rewrite.

A more structured approach would be like this, using a do-while loop to validate the input:

public static void insertRemove() {
    Scanner in = new Scanner(System.in);
    int selection;
    do {
        selection = in.nextInt();
    } while(!checkValid(selection));

    // selection is now valid so do whatever you need to
}

public static boolean checkValid(int selection) {
    for(int i = 0; i < array.length; i++) {
        if(array[i] == selection) {
            return true;
        }
    }

    return false;
}

It might also be useful for checkValid to return an index. You'd return i if the number was found or return -1 at the end to indicate the number was not found. This would let you perform the replace more conveniently. It could be rewritten like this:

public static void insertRemove() {
    Scanner in = new Scanner(System.in);
    int selection;
    int index;
    do {
        selection = in.nextInt();
        index = getIndexOf(selection);
    } while(index < 0);

    // ask user for a new number
    selection = in.nextInt();
    array[index] = selection;
}

Very structured, much easier to follow.

Radiodef
  • 37,180
  • 14
  • 90
  • 125
  • Thanks a lot will definitely consider re-writing this. It is pretty messy.... I think the -1 method will work much easier if not I could just rethink everything and try to do it with less randomness. – Adamc23 Mar 03 '14 at 05:19
  • No problem. The structured approach is better. I wouldn't fault you for inventing your own solution but a do-while is the right way to do this. See my edit--shows quick example of what it would look like with a method returning the index. – Radiodef Mar 03 '14 at 05:28
1

As you are doing this in java it is possible to break out of nested loops using a label as demonstrated in Breaking out of nested loops in Java you can use a label at the level of the loop you want to break to

public class Test {
  public static void main(String[] args) {
    outerloop:
    for (int i=0; i < 5; i++) {
      for (int j=0; j < 5; j++) {
        if (i * j > 6) {
          System.out.println("Breaking");
          break outerloop;
        }
        System.out.println(i + " " + j);
      }
    }
    System.out.println("Done");
  }
}
Community
  • 1
  • 1
clancer
  • 613
  • 4
  • 10
  • 1
    While syntactically correct this is just like a `goto` and if you ever have you resort to `goto` you really need to rethink your code. – Pedantic Mar 03 '14 at 05:05
  • 1
    When recursing over many dimensions your talking about nested loops anyway.. simply goto to the end of such a block is not a bad way to use such a tool.. goto always had a purpose it was just misused... python has a better way to break nested loops though – clancer Mar 03 '14 at 05:08
  • In 15 years of writing c/c++/java as a living, including data analysis on multidimensional data sets I've never had to use `goto.` Except in Fortran :( – Pedantic Mar 03 '14 at 05:12
  • 1
    @Pedantic: **Every** control statement is just syntactic sugar for a `goto`; saying this is like a `goto` is like saying an if statement is like a `goto`: it's true, but that doesn't mean it suffers from the problems that come with *unrestricted* use of `goto`. – Mark Peters Mar 03 '14 at 05:16
  • Every control statement is syntactic sugar for goto, indeed. But it doesn't mean you should use goto, use the sugar instead. – Pedantic Mar 03 '14 at 05:28