Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java for-loop condition behaves differently when using length() compared to using an int

I've recently started to learn Java and I've encountered a problem with for-loops. Here's a code snippet:

for (int c = 0; c < inputString.nextLine().length(); c++) {
            Random randomIndex = new Random();
            currentString.append(alphabet[randomIndex.nextInt(26)]);
}

System.out.println(currentString.toString());

In the code above, I attempt to create a string of random characters that is the same length as a string that the user has inputted. However, the loop only runs once. For example, if I were to input a string of length 4, I would get a one-character string.

If I hard-code the loop condition like this

for (int c = 0; c < 4; c++) { // We should have a 4-character string.
            Random randomIndex = new Random();
            currentString.append(alphabet[randomIndex.nextInt(26)]);
}

System.out.println(currentString.toString());

I get what I was expecting, a 4-character long string.

Is there some property about the length() method I'm missing? Even running System.out.println(inputString.nextLine().length()) gives me the expected length of the input string. What's going on?

like image 904
Scene Avatar asked May 19 '26 15:05

Scene


1 Answers

I'd like to expand on the (correct) accepted answer.

The basic for statement:

for ( [ForInit] ; [Expression] ; [ForUpdate] ) Statement 

is described in the JLS as:

14.14.1. The basic for Statement

The basic for statement executes some initialization code, then executes an Expression, a Statement, and some update code repeatedly until the value of the Expression is false.

i.e. the Expression, the Statement and the update code are executed multiple times, until the value of Expression is false.

In your case Expression is

c < inputString.nextLine().length()

and (assuming inputString is a Scanner), each time that expression is evaluated, it read a new input line, and compares its length to current value of c.

This means that if you first input a 4 character String and press enter, the condition will be true, since c == 0 and 0 < 4.

However, the next time the expression is evaluated, a new input line is expected. If you just press enter (which I assume you did, given the output you got), the new input String will be an empty String, so the condition would be 1 < 0, which is false, and the loop will end outputting a single character String.

Note that if instead of pressing enter, you entered 3 more Strings of at least 4 characters, the loop would have continued and would have produces a 4 character random String if you entered an empty String (or actually, any String of length <= 4) after the 4th iteration.

For example, the following 5 input lines:

1234
1234
1234
1234
1234

result in an output String of length 4

fwpl

Of course, the correct solution is to read just one input line, and use its length to determine the number of iterations of the loop:

Random randomIndex = new Random();
int length = inputString.nextLine().length();
for (int c = 0; c < length; c++) {
    currentString.append(alphabet[randomIndex.nextInt(26)]);
}

Note that I moved the instantiation of the Random instance outside the loop, since there's no reason to create a new instance for each iteration of the loop.

System.out.println(currentString.toString());
like image 179
Eran Avatar answered May 21 '26 03:05

Eran