I am trying to understand the scope of the for loop by testing out the following three examples:
Example 1:
int a=15;
for(a=1;a<3;a++) {
cout<<a<<endl;
}
cout<<a<<endl;
Here the console displays 1 2 3. However, I would have thought that it should display 1 2 15, since normally it seems that the scope of the variable a inside the for loop remains inside the for loop.
Example 2:
for (int a=1; a<3; a++) {
cout<<a<<endl;
}
cout<<a<<endl;
In this example the compiler does not recognize the variable a after the for loop - as expected. So how was it able to be recognised it in Example 1?
Example 3:
int a=15;
for(int a=1;a<3;a++) {
cout<<a<<endl;
}
cout<<a<<endl;
In this case the console displays 1 2 15. What is the difference between this and Example 1?
Thank you in advance for your help.
Analyzing your example 1:
int a=15;
This line declares a variable a. This variable can be read from or written to. It is valid until the end of the block where it is declared. Here, there is no such block visible; in a real program, blocks are code between { and }.
for(a=1;a<3;a++) {
cout<<a<<endl;
}
In these lines, you modify the variable from the first line. It is still the same variable, it’s only the value of the variable that changes. Imagine a variable like a sheet of paper. The sheet stays the same for the whole time, it’s just that you write different numbers on it (with a pencil) and erase them (with a rubber gum).
cout<<a<<endl;
Since there was no corresponding }, the variable a is still visible here.
Example 3 differs in one word from example 1: the int in the for loop. This int is a new variable declaration. Now you have two variables with the name a. Using the analogy of the paper sheets, you just grabbed another sheet of paper and laid it above your first sheet. The first sheet thereby becomes invisible.
At the end of the for loop, at the closing }, you take the upper sheet (which at that point has the number 3 written on it) and throw it in the waste bin. This makes the outer sheet appear again, which still has the value 15 written on it.
In example 1, you declare a outside the scope of the for loop, and then do not re-declare it (i.e. int a). For this reason, the variable a both inside and outside the loop is the same. In the first iteration, it is 1, then gets incremented to 2. It still meets the for loop criteria, so it executes again, and then increments to 3. Now, a doesn't meet the for loop criteria, so it leaves the loop with a value of 3. Finally, it is printed again, and its value is 3.
The reason that a is not recognized outside the loop in example 2 is that a was never declared outside the loop. It is a variable local to the for loop, and therefore does not exist in any scope outside that loop.
In example 3, you declare a a second time, when in the for loop declaration you say int a = 1 rather than just a = 1. This means that there is an a local to the for loop, and an a outside this loop, which maintains its value from before the loop executing, since they are two different variables - they have the same name but different scopes.
Solution For Ex 1:
In the first example you have declared var 'a' at the first line i.e before for loop is executed,initially the value is 15 but then in for loop you initialize it to 1,for loop iterates two times thus resulting in 1 and 2.In the third iteration 'a' is incremented thus now a=3 but condition fails as 'a' is not less than 3.So it prints 3 at the end.
Solution For Ex 2:
As variable is declared in for loop its scope lies within the for loop itself thus the variable is not accessible outside for loop.Thus Error
Solution For Ex 3:
The difference between the Ex1 and Ex3 is in Example 3 we have two copies of 'a',one is outside for loop whose value is 15 and one inside the for loop whose scope is within the for loop.So inside for loop var 'a' results into 1 2 as output and the outer var a results into 15 at the end.
Related
Our teacher for our introductory C++ course was speaking on the nature of for loops and how everything within the parentheses can be empty as long as the semicolons are there. My question is, if I were to take two for loops, one after the other, that have the same variable involved in their update statements, is it consistent across all compilers that, once the first for loop is exited, the second will just pick up the value of the variable that came about from the first loop if you keep the initial statement of the second loop empty? Our teacher was uncertain as to whether this interaction was compiler-specific; it worked in VS2017, but she expressed doubt as to whether it would work in earlier versions.
If your variable is part of the first for loop:
for(int x = 0; 10 > x; ++x)
{
}
for(; 20 > x; ++x)
{
}
then per the standard 'x' is not even defined for the second loop and the code will not compile. Note that some older compilers don't follow the standard on this point and will behave as in the next example.
If the variable is defined outside the first for loop:
int x = 0;
for(; 10 > x; ++x)
{
}
for(; 20 > x; ++x)
{
}
then when the second loop is entered 'x' will have the value it had at the time the first loop ended. In no case will 'x' be re-initialized by the second loop, or have some otherwise random value. It will either have the value obtained at the end of the first loop or result in a compilation error.
This question already has answers here:
What does it mean when the first "for" parameter is blank?
(8 answers)
Closed 4 years ago.
I'm studying for my exam and I bumped into this example that has a line that says:
for(;i<=m;i++)
The thing I don't understand is why is there a ; with nothing in front of it?
what does it do? What does it mean?
A for statement has the following syntax:
for (declaration; condition; post-condition)
The declaration happens once and once only. The condition is checked at the start of each loop and determines whether the loop will proceed, and the post-condition happens at the end of the loop.
Any and all of these statements can be omitted.
Yours is simply a for loop that does not require a declaration, perhaps because something is already declared, like so:
int i = 0;
for (;i<=m;++i)
If you wanted a loop to run indefinitely, you could omit the second statement:
for (int i = 0; ;++i)
In this regard, infinite loops are typically written as
for (;;)
You may wish to omit the post-condition, perhaps because you're using iterators and change it during the loop
for (auto it = std::begin(v); it != std::end(v);)
what does it do, what does it mean ?
It means that the initializing part of the for-loop is empty, i.e. no loop-variable is initialized in the scope of the loop.
This construct is most common in situations where you want to access the loop variable after the loop is left, e.g. in
int i = 7;
for(; i < 100; ++i) {
if(isPrime(i)) break;
}
assert(i == 11); // can access i now
This means a part of this statement is declared somewhere before.
i=0
for(;i<=m;i++)
This loop says,for every time that i is smaller than m, I'm going to do whatever is in the code block. Whenever i reaches m value, I'll stop. After each iteration of the loop, it increments i by 1 (i++), so that the loop will eventually stop when it meets the i <=m.
The thing that i don't understand is why is there a ";" with nothing in front of it. what does it do, what does it mean.
It is a valid statement that does nothing.
You can have empty statements any where you like. It's quite common to see them in looping constructs.
The i variable must have been initialized somewhere else.. so it picks the value from there and the loop iterates from that value of i.
I was always under the impression that a variable declared in any kind of loop statement is scoped to that statement alone. And a little poking around in similar questions seems to confirm this idea. So I am puzzled by the following excerpt from Stroustrup's A Tour of C++ (§4.2.3 Initializing Containers p. 38):
"The push_back() is useful for input of arbitrary numbers of elements. For example:
Vector read(istream& is) {
Vector v;
for (double d; is>>d;) // read floating-point values into d
v.push_back(d); // add d to v
return v;
}
The input loop is terminated by an end-of-file or a formatting error. Until that happens, each number
read is added to the Vector so that at the end, v’s size is the number of elements read. I used a for-statement rather than the more conventional while-statement to keep the scope of d limited to the loop."
This seems to imply that variables declared in the condition of a while statement persist outside the statement body.
Let's examine that loop:
for (double d; is>>d;) // read floating-point values into d
v.push_back(d); // add d to v
Here we have:
a declaration of d
a loop condition
an empty "do on each iteration" expression
And, yes, d is limited in scope to the for loop.
Now try writing a while loop to do the same job, keeping d limited in scope. You won't be able to, because there's no place to put a declaration in the preamble of a while. Only for has that feature. A while only has a condition.
That doesn't mean the scoping rules are different for while; it only means that it is not possible to write this code using while. There aren't any "variables declared in the condition of a while statement".
[..] that variables declared in the condition of a while statement [..]
That's not possible.
Using a for statement allows to declare a variable like this
for(int a = 0; a < 5; a++) {
// Use a
}
// a is not visible anymore
If you use a while loop, it is visible
int a = 0;
while(a < 5) {
// Use a
a++;
}
// a still visible
I'm coding a simple function using std::vector below where input is an integer vector and the function proceeds the iteration based on the number of elements in the vector.
In terms of space and time efficiency, which following code are suitable?
HugeClass is actually a Big Integer which contains complex arithmetic while I put a simple arithmetic below for simplicity.
1) Gives a dimension of vector
void (HugeClass& huge, std::vector<int>& vec, int dim){
for(int i=0;i<dim;i++){
huge+=vec[i];
}
}
2) Calls a std::vector.size() to iterate
void (HugeClass& huge, std::vector<int>& vec){
for(int i=0;i<vec.size();i++){
huge+=vec[i];
}
}
dim can range in [100,1000000]
The syntax of a for loop in C++ is:
for ( init; condition; increment ) {
statement(s);
}
Here is the flow of control in a for loop:
The init step is executed first, and only once. This step allows you to declare and initialize any loop control variables. You are not required to put a statement here, as long as a semicolon appears.
Next, the condition is evaluated. If it is true, the body of the loop is executed. If it is false, the body of the loop does not execute and flow of control jumps to the next statement just after the for loop.
After the body of the for loop executes, the flow of control jumps back up to the increment statement. This statement allows you to update any loop control variables. This statement can be left blank, as long as a semicolon appears after the condition.
So in the case of
for(int i=0;i<vec.size();i++) {
huge+=vec[i];
}
vec.size() called each time but is probably inlined, and is probably a simple function.
On top of which
A smart enough optimizer may be able to deduce that it is a loop invariant with no side effects and elide it entirely (this is easier if the code is inlined, but may be possible even if it is not if the compiler does global optimization)
I am talking with reference to C++.
I know that if an int is declared as static in recursion, its value is not reinitialized in stack-recursion call and the present value is used.
But if a stack becomes empty(or a recursion computation is complete) and then the recursion is called again, will it use the same static value as initialized in first stack call??
I will explain my problem in detail.
I am trying to code level order traversal in spiral form.
1
/ \
2 3
/ \ / \
7 6 5 4
Level order traversal in spiral form will give output 1 2 3 4 5 6 7.
void LevelSpiral(node* root, int level)
{
static int k = level%2;
if(root==NULL)
return;
if(level==1)
{
printf("%d ",root->val);
}
else
{
if(k==0)
{
LevelSpiral(root->left,level-1);
LevelSpiral(root->right,level-1);
}
else
{
LevelSpiral(root->right,level-1);
LevelSpiral(root->left,level-1);
}
}
}
void LevelOrderSpiral(node* root)
{
for(int i=1;i<=maxheight;i++)
LevelSpiral(root,i);
}
LevelOrderSpiral function makes separate LevelSpiral-call for each i. But throughout the code it always uses k=1(which is initialized in the first LevelSpiral-call with i=1) and prints the output as 1 3 2 4 5 6 7.
Shouldn't it print 1 2 3 4 5 6 7 as the function stack is reinitialized for every i?
You need a static variable for it's value to be retained between calls, or from one call to the next recursive call.
Furthermore, recursion wouldn't be the first tool I reach for a breadth-first traversal. I would use a queue of node (safe) pointers (or reference wrappers or whatever). Put the root node in the queue, then loop until the queue is empty removing the front element and enqueueing all of it's child nodes and do what you want with the recently removed element.
Regarding your implementation, you are alternating between going to the left first and going to the right first. level always equals 1 at the row before the one you want to print, so you always traverse your printing row from right to left. You'll see bigger shufflings of the nodes when you have a deeper tree. Draw a sample tree on paper and draw the navigations on it as you follow your code by hand.
I know that if an int is declared as const in recursion, its value is not reinitialized in stack-recursion call and the present value is used.
No, that’s wrong. const has got nothing to do with recursion or reentrancy.
But if a stack becomes empty(or a recursion computation is complete) and then the recursion is called again, will it use the same const value as initialized in first stack call??
A const is a normal (albeit unmodifiable) variable: it is reinitialised whenever the initialisation statement is executed, i.e. on every function call. This is the same for any non-static variable.
static local variables exhibit the behaviour you are describing: they are only executed once, at the first call of that function, and, importantly, they are not reinitialised even after the call stack is “emptied”. It makes no difference whether the function is called repeatedly from outside, or recursively.