david mah david mah - 1 month ago 12
Java Question

Changing input loop condition skips half of input values

So I wrote a program that creates a red black tree and determines the percentage of red nodes in the tree. Right now I'm making the main method for it. So here's what I have right now:

public static void main(String[] args) {
Scanner s;
if (args.length > 0){
try{
s = new Scanner(new File(args[0]));
} catch(java.io.FileNotFoundException e){
System.out.printf("Unable to open %s\n",args[0]);
return;
}
System.out.printf("Reading input values from %s.\n",args[0]);
} else {
s = new Scanner(System.in);
System.out.printf("Enter a list of non-negative integers. Enter a negative value to end the list.\n");
}
RedBlackBST<String, Integer> st = new RedBlackBST<String, Integer>();
int i = 0;
while ((s.hasNextInt())){
int key = s.nextInt();
st.put(key, i);
i++;
}
double percent = percentRed();
System.out.println("There are " + redcount + " red nodes so");
System.out.println(percent + "% of the nodes are red");
}


What I'm trying to do is create a tree based on either a file of integers (so if the user runs the program by typing "java RedBlackBST test10.txt" which would contain 10 values to insert into the tree) or if the user doesn't specify a file then it would prompt the user to type in his own values and put a negative value at the end to end the list. Right now typing in your own values don't work but if you pass in a .txt file of numbers then it works exactly as intended. Now as for typing in your own values, I was thinking of changing the while loop to look like this:

while ((s.hasNextInt()) && (s.nextInt()) >= 0){


So what this is supposed to do is go through the list of values and if you hit a negative value in the list then it stops reading the values. The problem with this is that for some reason (even if I pass in a file) it only reads half the values for any array in integers. So how come changing the while loop has now made the program only read half the array values?

Also the
put
method that I'm calling is the insert method which inserts the values into the tree.

Answer

Assuming you literally made the precise change you mentioned, your loop would end up looking like:

while ((s.hasNextInt()) && (s.nextInt()) >= 0){
    int key = s.nextInt();
    st.put(key, i);
    i++;
}

Which calls nextInt() twice per iteration, which of course skips every other value, as nextInt() consumes the input.

One typical approach here is to declare key outside the loop so you have it available in the condition's scope, then assign and test it all in one go, like:

int key;
while ((s.hasNextInt()) && (key = s.nextInt()) >= 0){ // <- key is assigned *and* tested
    st.put(key, i);
    i++;
}

Thus, one nextInt() per iteration.