2

I am doing some exercises and I came across something, that I do not know much about. Below is a code and the part I Do not understand fully, I'll put in between stars, like *this*.

public int[] seriesUp(int n) {
  int[] result = new int[n * (n + 1) / 2];
  int i = 0;
  for (int j = 1; j <= n; ++j)
    for (int k = 1; k <= j; ++k)
      result[*i++*] = k;
  return result;
}

Can someone maybe explain what the difference between above and below is?

public int[] seriesUp(int n) {
  int[] result = new int[n * (n + 1) / 2];
  int i = 0;
  for (int j = 1; j <= n; ++j)
    for (int k = 1; k <= j; ++k)
      result[i] = k;
      *i++;*
  return result;
}

I changed the i++ in the index brackets to i and incremented the i below, but this gives a whole other output, even though in my eyes it is the same.

lealceldeiro
  • 14,342
  • 6
  • 49
  • 80
HenkieTee
  • 21
  • 5
  • 5
    You're missing braces. – SLaks Oct 23 '18 at 18:23
  • 2
    The braces on the for loops that is. – takendarkk Oct 23 '18 at 18:24
  • 2
    You should **always** use braces with for loops. The result of not using braces is in this case the cause of the two snippets of code behaving very differently. – MC Emperor Oct 23 '18 at 18:27
  • 1
    just indent the lines correctly, that is, the indentation of the new line should be less (spaces), same as the `return` - the `i++` command is outside both `for` loops [as suggested always using braces is better] – user85421 Oct 23 '18 at 18:29
  • 1
    The code you *intended* to write is equivalent, but there is a bug that is preventing it from giving you the expected results. See the above comments. This is one of the most common mistakes when modifying loop code: you meant to add a statement to the loop body, but you *actually* added it *outside* the loop. – Mike Strobel Oct 23 '18 at 18:44
  • The difference between increment index inside brackets and out of the brackets: one statement versus two statements! – user85421 Oct 23 '18 at 19:43

1 Answers1

4

TL;DR

This

for (int j = 1; j <= n; ++j)
  for (int k = 1; k <= j; ++k)
    result[i++] = k;

is equivalent to below code (formatted with curly braces), which increments i inside the two for-loop:

for (int j = 1; j <= n; ++j) {
  for (int k = 1; k <= j; ++k) {
    result[i++] = k;
  }
}

And this

for (int j = 1; j <= n; ++j)
  for (int k = 1; k <= j; ++k)
    result[i] = k;
    i++;

is equivalent to this code (formatted with curly braces), which increments i after the two for-loop are executed:

for (int j = 1; j <= n; ++j) {
  for (int k = 1; k <= j; ++k) {
    result[i] = k;
  }
}
i++;

Basically, when curly braces are not used, instructions such as for, while, if, etc, interpret only the next line as the code block to be executed as part of its statement.

In your case you replaced result[i++] = k; (one line) for (two lines)

result[i] = k;
i++

leaving, this way, the second line (i++) out of the statement to be executed by the for. Following the same principle, the outer loop ignores the i++ sentence too.

When curly braces and code formatting are correctly used, this should never happen.


Long Story

This is the for statement:

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

Where Statement can be (among others) an ExpressionStatement or a Block.

The ExpressionStatement you used by doing result[i++] = k; was an Assignment (two of them, actually: result[i] = k; and i = i + 1, but, in one line), which is:

LeftHandSide AssignmentOperator Expression
result[i]    =                  k         ; // leaving out the `++` operation for simplicity here

Now, when you changed to the second alternative, without using curly braces, the Statement used by the for is still the first line next to it

result[i] = k; // <-- this keeps being the `Statement` taken by the `for`
i++            // and this line is not considered as a statement to be used by the for anymore

But, if you would have used curly braces, this would have become a Block statement in the form

{ [BlockStatements] }

Where BlockStatements is

BlockStatement {BlockStatement}

And each BlockStatement can be (among others) a Statement. Thus you would have been able to put as many Assignments (remember this is a Statement) as you wish to be executed by the fors statements.


Further readings:

Community
  • 1
  • 1
lealceldeiro
  • 14,342
  • 6
  • 49
  • 80