Little_idiot
Little_idiot

Reputation: 135

JAVA program keeps blocking the terminal for input even when it's not supposed to take input

So I debugged and went to the base of the problem. Basically, I am running a few testcases and

 int no_of_test = Integer.parseInt(in.readLine());
 for(int t = 0;t<no_of_test;t++){//do something}`

Works fine. However,

for(int t=0;t<Integer.parseInt(in.readLine());t++){//do something}

Here, it keeps waiting for input after each iteration.

In python I could do for t in range(int(input()) and it wouldn't block for input after every iteration, why is that not the case in JAVA? What am I missing?

Upvotes: 0

Views: 93

Answers (5)

Behrang Saeedzadeh
Behrang Saeedzadeh

Reputation: 47971

According to the Java Language Specification:

BasicForStatement:
    for ( ForInitopt ; Expressionopt ; ForUpdateopt ) Statement

ForStatementNoShortIf:
     for ( ForInitopt ; Expressionopt ; ForUpdateopt ) StatementNoShortIf

ForInit:
     StatementExpressionList
     LocalVariableDeclaration

ForUpdate:
    StatementExpressionList

StatementExpressionList:
    StatementExpression
    StatementExpressionList , StatementExpression

14.14.1.2. Iteration of for Statement

   Next, a for iteration step is performed, as follows:

     If the Expression is present, it is evaluated. If the result is of type Boolean, it is subject to unboxing conversion (§5.1.8).

In other words, t < Integer.parseInt(in.readLine()) is executed once per each iteration of the loop.

It is explained better in the Java Tutorial:

The for statement provides a compact way to iterate over a range of values. Programmers often refer to it as the "for loop" because of the way in which it repeatedly loops until a particular condition is satisfied. The general form of the for statement can be expressed as follows:

for (initialization; termination; increment) {
    statement(s) }

When using this version of the for statement, keep in mind that:

  • The initialization expression initializes the loop; it's executed once, as the loop begins.
  • When the termination expression evaluates to false, the loop terminates.
  • The increment expression is invoked after each iteration through the loop; it is perfectly acceptable for this expression to increment or decrement a value.

If you want something similar to for t in range(int(input()), you can use the Streams API:

import static java.lang.Integer.parseInt;
import static java.lang.System.console;

// option 1
try (final BufferedReader console = new 
           BufferedReader(new InputStreamReader(System.in))) {
  IntStream.range(0, parseInt(console.readLine())).forEach(i -> {
    System.out.println(i);
  });
}

// option 2 (fails in some IDEs as console() will return null)
IntStream.range(0, parseInt(console().readLine())).forEach(i -> {
  System.out.println(i);
});

Upvotes: 0

ilinykhma
ilinykhma

Reputation: 990

There are different code constructions.

In the Python sample range() is function. It's called once and returns integer sequence as a result. So, loop iterates over the sequence of values.

In the Java sample t < Integer.parseInt(in.readLine()) is the loop condition and it must be checked for every iteration. Java analog to your python code can be:

IntStream.range(0, Integer.parseInt(in.readLine())).forEach((e) -> {
    //...
});

Upvotes: 1

Aniket Sahrawat
Aniket Sahrawat

Reputation: 12937

It keeps waiting because second statement is a condition which is checked before each iteration.

for(int t=0; t<Integer.parseInt(in.readLine()); t++)
  • Statement 1: sets a variable before the loop starts (int t = 0).

  • Statement 2: defines the condition for the loop to run. If the condition is true, the loop will start over again, if it is false, the loop will end.

  • Statement 3: increases a value (t++) each time the code block in the loop has been executed.

The only case when a loop can end is when you don't give a input which will keep waiting for long till you enter one, so it's a never ending loop.

If you still want to end the loop, input something which is not a number.

Upvotes: 1

Not a JD
Not a JD

Reputation: 1902

With

for(int t=0;t<Integer.parseInt(in.readLine());t++){//do something}

The Integer.parseInt(in.readLine()) piece is re-evaluated every iteration.

Whereas with

int no_of_test = Integer.parseInt(in.readLine());
for(int t = 0;t<no_of_test;t++){//do something}

The Integer.parseInt(in.readLine()) is evaluated once only.

Upvotes: 1

Antoniossss
Antoniossss

Reputation: 32535

In first case you are doing in.read() outside the loop In second case, you got in.read() inside loop execution.

Remember that loop condition is evaluated on every iteration, so you are doinb in.read on every iteration.

Maybe you wanted to do this

for(int t=0,tests=<Integer.parseInt(in.readLine());t<tests;t++) {body}

?

Upvotes: 0

Related Questions