c++ for loop post-increment pre-increment difference - c++

i've been searching for an answer, but i get more and more confused.
i have these 2 for loops
for (int i = 1; (i < 5) && move.from[i - 1]; i++) {
int const departurePoint = move.from[i - 1];
int arrivalPoint = move.to[i - 1];
if (arrivalPoint < 0) { // A blot was hit
arrivalPoint = -arrivalPoint;
board[1 - turn][BAR - arrivalPoint]--; // Remove the blot
board[1 - turn][BAR]++; // and place it on the bar */
}
board[turn][departurePoint]--; // Move our own checker
board[turn][arrivalPoint]++; // to it's landing spot.
}
and
for (int i = 1; (i < 5) && move.from[i - 1]; ++i) {
int const departurePoint = move.from[i - 1];
int arrivalPoint = move.to[i - 1];
if (arrivalPoint < 0) { // We hit a blot
arrivalPoint = -arrivalPoint;
board[1 - turn][BAR - arrivalPoint]++; // Replace the blot
board[1 - turn][BAR]--; // remove it from the bar
}
board[turn][departurePoint]++; // Replace our own checker
board[turn][arrivalPoint]--; // to it's original spot.
}
my questions are:
In the for loop statement with pre-increment, has i been incremented when the "move.from[i - 1] is evaluated?
Has i been incremented in the body of the statement?

for (int i = 1; (i < 5) && move.from[i - 1]; i++ /*i increments here and nowhere else*/)
and
for (int i = 1; (i < 5) && move.from[i - 1]; ++i /*i increments here and nowhere else*/)
Both codes are equivalent. The difference is very slight and it does not apply to this example.
when i==3,
++i means:
4=i+1=(++i) then i=4.
i++ means:
3= i =(i++) then i=4.
it does not make a difference until you assign it to another variable:
for(...; ...; k=i++)
or
for(...; ...; k=++i)
i+1 means:
store i to a temporary variable. Increase the temporary variable by one. It reads i but does not write to i. i will change only on ++, -- or i= and a few other cases.

Your short question is What is the difference between i++ and ++i is the value of the expression?
The value i++ is the value of i before the increment. The value of ++i is the value of i after the increment.
Example:
int i = 2;
std::cout << i++ << std::cout; // shows 2
std::cout << i << std::cout; // shows 3
i = 2;
std::cout << ++i << std::cout; // shows 3
std::cout << i << std::cout; // shows 3
The i-- and --i operators works the same way.

The for loop takes two statements and an expresion like this:
for(init_statement;condition_expresion;progress_statement){
//...body...
}
The semantic of this instruction is basically the same as writing:
init_statement;
while(condition_expresion){
//...body...
progress_statement;
}
Notice the side effect of both i++ and ++i is the same, the variable i is incremented by one. Those two instructions are different when they are used as expresions, i++ evaluates to the value of i before the increment, and ++i evaluates to the value after the increment. This is all irrelevant for the for loop, as the value of the progression statement is discarded.

Related

Why does for loop output 0 as the first number and if I write the same for loop condition separately, it will output 1?

In my opinion, it should output 1 as the first number as variable i is initialized first, then the condition is checked and then it's incremented. When incremented, it should output 1 but it outputs 0 instead. Why?
int i = 0; i < 10; ++i;
cout << i;
// Outputs 1
for (int i = 0; i < 10; ++i)
cout << i;
// Outputs 0123456789 while having 0 as first number
int i = 0; i < 10; ++i;
cout << i;
This is not a loop. It executes the following things in order:
int i = 0; // sets it to 0
i < 10; // true (result is not stored)
++i; // increments to 1
cout << i;
In the first example, the statements are executed separately.
int i = 0; i < 10; ++i; // declare variable i, do comparision and discard the result, increment i
cout << i; // print i
In the second example, you have to know how for works.
for loop - cppreference.com
formal syntax:
attr(optional) for ( init-statement condition(optional) ; iteration_expression(optional) ) statement
iteration_expression - any expression, which is executed after every iteration of the loop and before re-evaluating condition. Typically, this is the expression that increments the loop counter
The above syntax produces code equivalent to:
{
init_statement
while ( condition ) {
statement
iteration_expression ;
}
}
As you see, the iteration_expression ++i is executed after the execution of the loop body, in which i is printed. Therefore, the initial value of i, which is 0, is printed in the first iteration.

Iteration variable goes out of range in for-loop

I have a for-loop in my function:
for (int i = vector1.size() - 1, j = vector2.size() - 1;i >= vector1.size() - Get_polynomial_power(vector1) - 1;--i, --j) {
// some code
something = vector1.at(i); // <- here i goes out of range
}
The problem is that iteration variable i goes out of range.
Condition for exiting from loop is set with i >= vector1.size() - Get_polynomial_power(vector1) - 1; which equals to i >= 0 in my specific case (Get_polynomial_power is user defined function that returns some int value).
And the last value of i is -1. So the program terminates with thrown exception "out of range".
But if I set condition for exiting the loop directly with 0, so it looks like:
for (int i = vector1.size() - 1, j = vector2.size() - 1;i >= 0;--i, --j) {
// some code
something = vector1.at(i); // <- here i doesn't go out of range
}
then there is no error and the last value of i is 0 so it doesn't go out of range.
So the question is: why doesn't iteration variable goes out of range if condition for exit from loop is set directly via 0, but if it is set with a statement that is equals to 0 then the error appears?
I tried a solution with loop-local value as was told in other similar questions, like:
for (int i = vector1.size() - 1, j = vector2.size() - 1;i >= vector1.size() - Get_polynomial_power(vector1) - 1;--i, --j) {
// some code
int index = i;
something = vector1.at(index);
}
but it didn't change the thing.
Just in case, here is full code of my function:
vector<int> Polynomial_addition_substraction(vector<int> polynomial1, vector<int> polynomial2) {
vector<int> addition_substraction_result;
vector<int> vector1;
vector<int> vector2;
if (Get_polynomial_power(polynomial1) >= Get_polynomial_power(polynomial2)) {
vector1 = polynomial1;
vector2 = polynomial2;
}
else {
vector1 = polynomial2;
vector2 = polynomial1;
}
for (int i = vector1.size() - 1, j = vector2.size() - 1;i>=vector1.size()-Get_polynomial_power(vector1)-1;--i,--j) {
if (j < 0) {
addition_substraction_result.insert(addition_substraction_result.begin(), vector1.at(i));
}
else {
addition_substraction_result.insert(addition_substraction_result.begin(), vector1.at(i) ^ vector2.at(j));
}
}
return addition_substraction_result;
}
The issue is due to .size() evaluating to an unsigned type and the subsequent subtraction happening therefore in unsigned arithmetic. (The int in an expression containing an unsigned and and int is converted to an unsigned.) This effect is particularly noticeable if the vector is empty.
So wraparound effects take the expression value to a large unsigned number, and that yields a subscripting error.
The solution is to write an expression of the form
i > size() - a
as
i + a > size()

Shifting Objects Up in an Array

I'm creating a program that creates an array of objects in random positions in an array size 8. Once created, I need them to sort so that all the objects in the array are shifted up to the top, so no gaps exist between them. I'm almost there, but I cannot seem to get them to swap to index 0 in the array, and they instead swap to index 1. Any suggestions? (Must be done the way I'm doing it, not with other sorting algorithms or whatnot)
#include <iostream>
#include <string>
#include <ctime>
using namespace std;
struct WordCount {
string name = "";
int count = 0;
};
int main() {
cout << "Original random array: " << endl;
srand(static_cast<int>(time(0)));
int i = 0;
WordCount wordArr[8];
while (i < 4) {
int randomNum = 0 + (rand() % static_cast<int>(7 + 1));
if(wordArr[randomNum].name == "") {
wordArr[randomNum].name = "word" + static_cast<char>(i);
wordArr[randomNum].count = i;
i++;
}
}
int j = 0;
while (j < 8) {
cout << wordArr[j].name << " " << wordArr[j].count << endl;
j++;
}
cout << "\n\nSorted array: " << endl;
for (int i = 7; i >= 0; i--) {
for (int j = 0; j <= 7; j++) {
if (wordArr[i].name != "") {
if (wordArr[j].name == "") {
WordCount temp = wordArr[i];
wordArr[i] = wordArr[j];
wordArr[j] = temp;
}
}
}
}
int k = 0;
while (k < 8) {
cout << wordArr[k].name << " " << wordArr[k].count << endl;
k++;
}
return 0;
}
If I understand your requirement correctly, you want to move all the non-blank entries to the start of the array. To do this, you need an algorithm like this for example:
for i = 0 to 7
if wordArr[i].name is blank
for j = i + 1 to 7
if wordArr[j].name is not blank
swap [i] and [j]
break
So, starting from the beginning, if we encounter a blank entry, we look forward for the next non-blank entry. If we find such an entry, we swap the blank and non-blank entry, then break to loop again looking for the next blank entry.
Note, this isn't the most efficient of solutions, but it will get you started.
Note also I'd replace the 4 and 8 with definitions like:
#define MAX_ENTRIES (8)
#define TO_GENERATE_ENTRIES (4)
Finally:
wordArr[randomNum].name = "word" + static_cast<char>(i);
That will not do what you want it to do; try:
wordArr[randomNum].name = "word" + static_cast<char>('0' + i);
To append the digits, not the byte codes, to the end of the number. Or perhaps, if you have C++11:
wordArr[randomNum].name = "word" + std::to_string(i);
I see couple of problems.
The expression "word" + static_cast<char>(i); doesn't do what you are hoping to do.
It is equivalent to:
char const* w = "word";
char const* p = w + i;
When i is 2, p will be "rd". You need to use std::string("word") + std::to_string(i).
The logic for moving objects with the non-empty names to objects with empty names did not make sense to me. It obviously does not work for you. The following updated version works for me:
for (int i = 0; i <= 7; ++i) {
// If the name of the object at wordArr[i] is not empty, move on to the
// next item in the array. If it is empty, copy the next object that
// has a non-empty name.
if ( wordArr[i].name == "") {
// Start comparing from the object at wordArr[i+1]. There
// is no need to start at wordArr[i]. We know that it is empty.
for (int j = i+1; j <= 7; ++j) {
if (wordArr[j].name != "") {
WordCount temp = wordArr[i];
wordArr[i] = wordArr[j];
wordArr[j] = temp;
}
}
}
}
There was two problems as :
wordArr[randomNum].name = "word" + static_cast<char>(i); this is not what your are looking for, if you want that your names generate correctly you need something like this :
wordArr[randomNum].name = "word " + std::to_string(i);
Your sorting loop does not do what you want, it's just check for the "gaps" as you said, you need something like this :
for (int i = 0; i < 8; ++i) {
for (int j = i+1; j < 8; ++j) {
if (wordArr[i].name == "" || (wordArr[i].count < wordArr[j].count)) {
WordCount temp = wordArr[i];
wordArr[i] = wordArr[j];
wordArr[j] = temp;
}
}
}
Your algorithm sorts the array, but then looses the sorting again.
You want to swap elements only when i > j, in order to push elements to the top only. As a result, you need to change this:
if (wordArr[j].name == "")
to this:
if (wordArr[j].name == "" && i > j)
Consider this array example:
0
ord 1
0
0
rd 2
word 0
d 3
0
Your code will sort it to:
d 3
ord 1
word 0
rd 2
0
0
0
0
but when i = 3, it will try to populate the 5th cell, and it will swap it with rd 2, which is not what we want.
This will push rd 2 down, but we don't want that, we want gaps (zeroes) to go to the end of the array, thus we need to swap eleemnts only when they are going to go higher, not lower, which is equivalent to say when i > j.
PS: If you are a beginner skip that part.
You can optimize the inner loop by using one if statement and a break keyword, like this:
for (int j = 0; j <= 7; j++) {
if (wordArr[i].name != "" && wordArr[j].name == "" && i > j) {
WordCount temp = wordArr[i];
wordArr[i] = wordArr[j];
wordArr[j] = temp;
break;
}
}

What does it mean for an array to have incremented element in square brackets?

In the following algorithm for merge-sort, within the 3rd definition, first while loop there is:
a[k++] = (a[j] < b[i]) ? a[j++] : b[i++].
I understand that the RHS is a conditional statement stating that if the first operand is satisfied, then we should perform the second operand, and if it is not satisfied, we should perform the third operand.
What element does a[k++], a[j++] and b[i++] correspond to?
From my understanding, it should mean in each successive while loop, the element is incremented.
ie. beginning with the initialised values (i=1, j=m+1, k=1) for the first while loop, the next while loop will consist of (i=2, j=m+2, k=2), and so on.
Here is the entire algorithm:
# split in half
m = n / 2
# recursive sorts
sort a[1..m]
sort a[m+1..n]
# merge sorted sub-arrays using temp array
b = copy of a[1..m]
i = 1, j = m+1, k = 1
while i <= m and j <= n,
a[k++] = (a[j] < b[i]) ? a[j++] : b[i++]
→ invariant: a[1..k] in final position
while i <= m,
a[k++] = b[i++]
→ invariant: a[1..k] in final position
a[k] takes the kth element of the array a.
k++ increases the value of k, but returns the previous value.
Thus, a[k++] returns a[k] with the side-effect of increasing k after returning the value of a[k]. a[k++] = 4 is equivalent to:
a[k] = 4
k = k + 1
On the other hand, ++k would increase k before returning it, so a[++k] = 4 would be
k = k + 1
a[k] = 4
The increment and decrement operators work the same in array subscripts as they do in other locations. The postfix version increments the variable and returns its original value, and the prefix version increments the variable and returns its new value.
int i = 0;
do {
if (i++) { std::cout << "i > 0" << std::endl; }
} while (i < 10);
// Checks "i"'s original value.
// First check fails, because i was 0 before incrementing.
// Outputs line 9 times.
// -----
int i = 0;
do {
if (++i) { std::cout << "i > 0" << std::endl; }
} while (i < 10);
// Checks "i"'s incremented value.
// First check succeeds, because i is incremented before being read.
// Outputs line 10 times.
Similarly, if we have this:
int arr[5] = { 1, 2, 3, 4, 5 };
int i = 0;
do {
std::cout << arr[i++] << std::endl;
} while (i < 5);
The variable's original value will be used as the index, and the output will be:
1
2
3
4
5
However, if we have this:
int arr[5] = { 1, 2, 3, 4, 5 };
int i = 0;
do {
std::cout << arr[++i] << std::endl;
} while (i < 5);
The variable's incremented value is used as the index, and the output will be:
2
3
4
5
Considering this, we can take your example line, a[k++] = (a[j] < b[i]) ? a[j++] : b[i++], and read it as meaning this:
Assign value to a[k], then increment k.
Value is conditionally determined based on:
(a[j] < b[i])
If true, value is:
Read a[j], then increment j.
If false, value is:
Read b[i], then increment i.
It can be a useful time-saver if you know how to use it properly, but it can also make things harder to parse if used improperly.

What is the purpose of the increment statement?

Why are increment statements a thing in for-loops in C++? To me it seems redundant, because you could simply put the increments inside the conditional code. Am I misunderstanding something important here?
To illustrate my question better, I'm including some pseudocode:
What is the difference between ->
for( int a = 10; a < 20; a = a + 1 )
{
cout << a << endl;
}
and
for( int a = 10; a < 20;)
{
a = a + 1
cout << a << endl;
}
It's more than mere convenience sometimes.
These are equivalent:
for (int a = 10; a < 20; a = a + 1) {
cout << a << endl;
}
for (int a = 10; a < 20; ) {
cout << a << endl;
a = a + 1;
}
But, these are not:
// this works ...
for (int a = 10; a < 20; a = a + 1) {
if (blah ...)
continue;
cout << a << endl;
}
// this doesn't
for (int a = 10; a < 20; ) {
if (blah ...)
continue;
cout << a << endl;
a = a + 1;
}
Since you're coming from python, an idiomatic for loop is like a python range, but much more powerful. Your C for loop, expressed in python would be:
for a in range(10,20,1)
It's more idiomatic to express this as:
for (a = 10; a < 20; a += 1)
Because the loop increment is 1, it's even more idiomatic to do this:
for (a = 10; a < 20; ++a)
But, for loops are:
for ([init_stmt]; [test_stmt]; [incr_stmt])
Where any of the *_stmt can be compound:
for (x = 0, y = 0; x < 10; ++x, y += 2)
Convenience.
However, your equivalent code should be:
for (int a = 10; a < 20;)
{
cout << a << endl;
a = a + 1;
}
It runs at the end of the loop body.
[ snips grumbling about quality of now deleted/ edited answers ;-) ]
This:
for (unsigned counter = 1; counter <= 10; ++counter) {
doStuff();
}
is largely equivalent to this:
unsigned counter = 1;
while (counter <= 10) {
doStuff();
++counter;
}
with the notable exception that, in the 1st case, you have the considerable benefit that counter is scoped only to within the for block and automatically goes out-of-scope as soon as it finishes - whereas with the latter, counter must remain in-scope after the loop, where it's potentially useless or even an obstacle.
(tangential: Note that C did not support within-for declaration, or any non-top-of-block declarations, until C99 - but barring extenuating circumstances, anyone not using at least C99 by now is making a questionable choice imho.)
edit: Craig also makes a very good point regarding continue - an oft-forgotten but certainly useful statement. I'm sure there are probably other differences we could conjure up.
for this example:
using namespace std;
int main(int argc, char** argv) {
for( int a = 10; a < 20;)
{
a = a + 1;
cout << a << endl;
}
return 0;
}
the output will be from 11-->20
the first example will be from 10-->19
your are putting the increment part outside the loop and this possible, but notice that the value 10 will not appear, because you are increment before printing the value of a
so in the 2nd example your printing the value and then increment, and at the end of the loop, you are quiting the loop without reaching 20, because the condition get you out the loop
executing code block before increment is the key for you, the for loop increment just after the code block is executed
Well it is not required, it is just for convenience.
In your second code, you made a little mistake which would make the code nonequivalent to the the first one.
Your increment should be at the end of loop in order to be equivalent to the first code
so it should rather be:
for( int a = 10; a < 20;)
{
cout << a << endl;
a = a + 1; //increment at the end of instructions
}
These little errors and also errors like forgetting to include your increment is why it is convenient to include the increment in the for loop.
Or you can use the while loop instead:
while (condition)
{//instructions here;}