Hey guys I have a question about variables and If statements.
The reason I am asking is I am assigning tokens in a vector of strings to variables but if my vector only has 3 elements and I try to assign a variable to myVector(5) I get an error.
This is my solution to that problem
std::string element5;
if(myVector.size () >= 4)
(
std::string element5 = myVector.at(4)
}
But that wont change the string outside the if statement? My code works fine if I have exactly 5 elements and no error check but if I'm passing in standard input I wont really know how many elements there are all I will know is that there are a max of 50 elements.
I dont need to ouput any elements just run this code on each one
if(countSubstring(element5,"a") > 0)
{
a = a + 1
}
then I would output a.
how do I make element5 keep its new string?
Problem
Your code here redefines your variable element5:
std::string element5;
if(myVector.size () >= 4)
(
std::string element5 = myVector.at(4)
}
Here you first declare element5 after the first line, and then you re-declare it at the third line in your if statement. That essentially "recreates" the variable element5 for that scope {}. And then of course is poped right after the scope. So you won't see a change in element5 if you try to print it out of the scope.
Solution
Easy, just don't re-declare your variable, and you're all set! Like so:
std::string element5;
if(myVector.size () >= 4)
(
element5 = myVector.at(4)
}
Why is this happening?
Like I said, down in the assembly level the variable gets pushed, and then suddenly when it comes down to another level and the same variable gets re-declared, the global variable gets forgotten about. And as soon as the scope ends:
{
//This is a scope
}
the re-declared variable gets poped off the stack, and we have our original element5 back! This will leave element5 in the same position since you didn't actually change it ;).
Undefined Behaviors(UB)
Don't reference to an out-of-scope object; don't do it!
C++: Reference to "out of scope" object
References
What happens when C++ reference leaves it's scope?
What happens in C++ when I pass an object by reference and it goes out of scope?
Glossary
scope: The "container" a program is currently executing under; for example, let's take this:
int main() {
//1st scope
if (true) {
//2nd scope
{
//third scope
}
}
}
Undefined Behavior(UB):
When in an undefined/unknown state at any time given during the compilation. Compiler does whatever it decides to do, making it a very dangerous Behavior especially if you are writing a big project! Here is a good question/answer to this topic:
https://softwareengineering.stackexchange.com/questions/99692/philosophy-behind-undefined-behavior
You are redefining the string inside the if statement, you shouldn't do that because you want to use the string that has been declared before.
So just replace std::string element5 = myVector.at(4) with element5 = myVector.at(4)
Related
So I have been working on a question and this think stumbled upon me. When I declare a variable outside the main function, the program works correctly, that is it reaches the else case of "Friendship is magic" but if the variable is declared inside it returns Chris instead of Friendship statement.
int mis, chr;
int main() {
int a, n, m;
cin >> a;
for (int i = 0; i < a; i++) {
//code here
}
if(mis > chr)
cout << "Mishka";
else if(chr > mis)
cout << "Chris";
else
cout << "Friendship is magic!^^";
}
The input that I am using makes the value of chr and mis equal so it should be evaluating to the else statement but instead it just stops at else if.
"With great power (provided by C++) there must also come great responsibility"
And
"With uninitialized variables comes the undefined behavior"
Variables that are declared at global scope are being initialized by the compiler. However, the variables defined inside any function (i.e, having automatic storage) may contain garbage values (that could be different in each invocation of the program). I recommend always initializing your variables to some value.
int main()
{
int mis = 0, chr = 0;
// ...
return 0;
}
Let's come to your program now:
When I declare a variable outside the main function, the program works correctly, that is it reaches the else case of "Friendship is magic"
It is happening because the variables (on which your if ladder dependent) are being initialized to 0. Since, both variables have same value (0), the else part of the if statement is being executed.
but if the variable is declared inside it returns Chris instead of Friendship statement.
It's a perfect example of undefined behavior. If they are defined inside your function, they will be holding some garbage value and that might not be equal. Hence, what you are observing is an undefined behavior and you might get different results in different machines or even sometimes in a same machine.
I tried your code and it works the same for me in both cases.
So, I would say it changes with editor to editor and always initialize the variable before using it.
Otherwise, we might face the same problem as you face. As it initializes the variables with garbage values.
I was reading C++ Primer by Stanley B. Lippman and at the part of flow control it shows an example of a for-loop like this one:
#include <iostream>
int main(void){
int sum=0;
for (int val=1; val <= 10; val++)
sum +=val;
std::cout << sum << std::endl;
return 0;
}
If I try std::cout << val; outside of the for-loop, the IDE gives me an error. But I want to understand why it happens and how it is different from this code:
#include <iostream>
int main(void){
int sum=0;
int val;
for ( val=1; val <= 10; val++)
sum +=val;
std::cout << sum << std::endl;
std::cout << val;
return 0;
}
Where I can actually print the val value without any problem.
Does it have something to do with local variable considering the for-loop a function that we are using inside of the main?
Every variable has scope, which is (loosely speaking) its lifetime.
A variable declared in the head of a for loop has scope limited to the for loop. When control passes out of the loop, the variable passes out of scope. Exactly the same thing happens to variables declared in a function, when control passes out of the function.
Does it have something to do with local variable considering the for-loop a function that we are using inside of the main?
Nothing to do with functions; there are plenty of other ways to get a scope, including a block:
int main()
{
{
int x = 0;
}
std::cout << x; // error
}
And a for loop is another example.
Its deliberate. Its called scope, Whenever you introduce a block { /*stuff here */ } (and a few other places) the variables inside the block are local to the block and supersede (hide) variables of the same name defined outside the block. It helps to ensure block-local code does not tread on other variables. Can be useful when editing an old codebase and you don't want to accidentally use a wider scoped variable.
The concept behind this is called Scope of the variable. Whenever a variable is created a memory location is assigned to it. So in order to optimize the memory usage scope of the variable is defined.
In the first case, the variable is limited only to the for loop. The variable is created inside at the beginning of the loop, utilized inside the loop and destroyed when the execution comes out of the loop.
In second case, the variable is created outside the loop so it persists till the execution of the program and hence you were able to access it even after the loop.
The variable declared inside the for loop is an example of local variable and that declared outside is an example of global variables.
Not only with the loops, the local variables will also be used in if..else blocks, functions and their usage is limited only within the scope.
Hope this answers your question.
Running this exact code does not turn up any errors for me. I get a value of 55 for sum and 11 for val as expected. Because you defined val outside of your for loop but in main, it should be good everywhere within the main() function to the best of my knowledge. As a general rule, if you declare a variable in between two curly braces without any fancy keywords, it should stay valid within those two curly braces (being "local" to that block of code). I am no c++ guru, so there might be exceptions to that (I am also not sure if "if" statements count as code blocks whose locally defined variables only work within the statement).
Someone told me: "declaring variables close to their use have value". He corrected me:
void student_score(size_t student_list_size) {
// int exam;
// int average;
// int digit;
// int counter_digits;
for (size_t i = 0; i < student_list_size; i++) {
int exam;
int average;
int digit;
int counter_digits;
I think it's bad, because here variables initialized every loop. What's true?
I encourage to declare them in as local a scope as possible, and as close to the first use as possible. This makes it easier for the reader to find the declaration and see what type the variable is and what it was initialized to. And of course, compiler will optimize it.
Both methods would be optimised to the same thing by the compiler. But for readability and ease of future maintenance, declaring the variables within the loop might be preferred by some.
I think it's bad, because here variables initialized every loop. What's true?
The code given the variables are not initialised at all.
So it is just a matter of personal taste.
It depends. C and C++ work differently in that regard. In C, variables MUST be declared at the start of its scope (forget that, it depends on your compiler although it holds true in pre-C99 compilers, as pointed out in the comments - thanks guys!), while in C++ you can declare them anywhere.
Now, it depends. Let's suppose the following two pieces of code:
int i = 0;
while (i < 5) {
i++;
}
while (i < 5) {
int i = 0;
i++;
}
In this case, the first piece of code is what's gonna work, because in the second case you declare the variable at each loop. But, let's suppose the following...
int i = 0;
while (i < 5) {
std::String str = "The number is now " + std::to_string(i);
cout << str << endl;
i++;
}
In short, declare the variables where it makes most sense to you and your code. Unless you're microoptimizing, like most things, it all depends on context.
This seems like a discussion with many personal opinions, so I'll add mine: I am a C programmer and like the C rules of having to declare your variables at the begining of a function (or block). For one thing, it tells me the stack lay-out so if I create another bug (I do "occassionaly") and overwrite something, I can determine the cause from just the stack lay-out. Then, when having to go through C++ code, I always have to search where the variable is declared. I rather look at the function beginning and see them all neatly declared.
I do ocassionally want to write for (int i=0;... and know the variable goes out of scope following the for loop (I hope it goes out of scope, as it is declared before the block begins).
Then there is an example in another answer:
while (i < 5) {
int i = 0;
i++;
}
and I hope it doesn't work because if it works it means there must be a variable i declared before this loop and so you have a clash of variables and scopes which can be horrible to debug (the loop will never terminate because the wrong i is incremented). I mean, I hope all variables must have been declared before their use.
I believe you must have a discipline in declaring your variables. The discipline can vary per person, just as long as it is easy to find where a variable is declared and what its scope is.
First of all that is not valid C code unless you are using -std=c99.
Furthermore, as long as you aren't creating dangling pointers in the loop, there is no problem with it.
The advantage you gain from doing it this way is that these variables are in a tight knit scope.
You need to know some knowledge of what local variable is ?
A variable declared inside a function is known as local variable. Local variables are also called automatic variables.
Scope: The area where a variable can be accessed is known as scope of variable.
Scope of local variable:
Local variable can be used only in the function in which it is declared.
Lifetime:
The time period for which a variable exists in the memory is known as lifetime of variable.
Lifetime of local variable:
Lifetime of local variables starts when control enters the function in which it is declared and it is destroyed when control exists from the function or block.
void student_score(size_t student_list_size) {
// int exam;
// int average;
// int digit;
// int counter_digits;
/* The above variable declared are local to the function student_score and can't be used
in other blocks. In your case its the for loop. */
for (size_t i = 0; i < student_list_size; i++) {
int exam;
int average;
int digit;
int counter_digits;
...
/* The above declared variable are local to the for loop and not to the function.*/
Consider this example:
#include<stdio.h>
void fun();
int main()
{
fun();
return 0;
}
void fun()
{
int i,temp=100,avg=200;
for (i=0;i<2;i++)
{
int temp,avg;
temp = 10 + 20;
avg = temp / 2;
printf("inside for loop: %d %d",temp,avg);
printf("\n");
}
printf("outside for loop: %d %d\n",temp,avg);
}
Output:
inside for loop: 30 15
inside for loop: 30 15
outside for loop: 100 200
If you are declaring the variable in loops the then declare the variable as static (In case if the value of the variable to be saved/used for further iteration).
Even compiler spend lot of time to initialize the variable in loops.
My suggestion is to declare at the beginning of the function. its a good programming practice.
I think, i made my point.
I am learning C++ using Robert Lafore's book ( OOP with C++ ).
In the book, I have encountered this example:
#include <iostream>
#include <conio.h>
using namespace std;
void main ()
{
int numb;
for ( numb = 1 ; numb <= 10 ; numb++ )
{
cout << setw(4) << numb;
int cube = numb*numb*numb;
cout << setw(6) << cube << endl;
}
getch();
}
The variable 'cube' has been declared as int 'inside the loop body'.
int cube = numb*numb*numb;
Since the loop iterates 10 times, the variable 'cube' will also get declared 10 times. 'cube' is accessible inside the loop body no matter what iteration. So, when we enter the loop body for, say, 2nd iteration, 'cube' is already known( because it already got declared during the 1st iteration), and another declaration for 'cube' should give an error of "redefinition". But instead, it builds successfully and debugs without a problem. Why?
The scope of an automatic variable (such as cube) is the block in which it is declared. The block that cube is declared in is the body of the for loop. At the end of each iteration, the cube variable goes out of scope, the next iteration starts and then cube is introduced to the scope again. Logically, there is no clash because no two identifiers cube exist in the same scope - in fact, there is only a single declaration of cube.
It might be worth distinguishing between the declaration of a variable and the creation of an object due to that declaration. There is only one declaration int cube = ...;. It doesn't matter that this piece of code may be reached many times; it's still only one declaration. The rules of the language say that you cannot declare two variables with the same name in the same scope, but that's okay since you're only declaring it once. This is a completely static rule that your compiler is able to analyse.
It just so happens that your declaration is reached 10 times because of your for loop, which means that 10 int objects will be created. Due to the scope of the variable, they won't all exist at the same time. This is not a static property of the program. The compiler cannot in general know beforehand how many times a line of code will be reached.
When you enter the loop a 2nd time, the first cube has gone out of scope so it's all OK.
Two cubes in the same scope would be a problem:
{
int cube = 0;
int cube = 1;
}
You've discovered "Automatic-storage duration".
The variable cube is declared inside the loop. Especially, inside the block-scope of the loop. At the end of the loop, this variable will be destroyed, just like any variable declared in any block-scope, be it a function, a loop, an if/else block, or just a raw block scope that you can declare anywhere in the code using { and }, i.e.:
int main(){
//Beginning of block
{
int cube = 1;
//cube exists and is declared here
}//End of block
//cube is gone here
return 0;
}
So in fact, every iteration of the loop will have its brand new and fresh cube variable.
The variable cube is only used inside the body of the for loop. I am not sure that saying it is declared ten times is correct (a declaration, actually a definition in your case, is a syntactic and static textual portion of source code).
In C++ you can (and you often do) have blocks with local variables. The scope of cube starts at it declaration and ends at the end of the containing block (braces { ... }).
If the type of a defined variable has a constructor, it is called at the definition point. If that type has a destructor, it is called conceptually at the end of the block (figuratively, just before the closing } ....).
The variable will be declared in each iteration of the loop, and then it will go out of scope as the block ({...}) ends, i.e. it will cease to exist. Then on the next iteration it will be declared again, which is not a redeclaration, since it didn't exist. It is said to be a "local variable", in this case local to the block.
As cube is defined inside the cycle body its scope will be that body. So after each iteration completes cube will go out of scope and on the next iteration a brand new cube will be created. This is what happens in theory. It may happen though that the compiler optimizes this code and only ever creates one variable. Either way the code is perfectly valid and will work as excepted.
The variable 'cube' is declared and defined in each iteration. The scope of 'cube' dies with the iteration and new declaration and definition in each loop happens.
suppose
while(1)
{
{
{
int a=10;
a=5;
}
}
}
now as I cannot refer to "a" after its block's brace. I want to know when control moves up to first brace and then running down visited third brace again will "a" declared again or "a" hold value 5.
A new a variable will be defined in each step of loop.
a will only be declared when you declare it...
You declared it inside an inner scope, so any code referring to a will only be valid inside the same scope. Once you leave that scope, there exists nothing in your program called 'a' any longer. The memory that used to hold the value 5 may now be used by the rest of the program for other purposes.
Logically, the a cant be reference before its declaration, or after the close of the brace pair its declared in. It also gets destructed at the close, but thats a NOP for ints.
Each time around the loop it will be re-initialized to 10.
But, you missed the fun part of the question, about what happens if the declaration doesnt set the value:
while(1)
{
{
int a; // Here Scope Starts
a=5;
}// Here Scope Ends
}
Here, a will be undefined before it is set the first time. But, it will also almost always be in the same place on the stack, so it might possibly retain value from one iteration to the next, if nothing else uses that space. But whether or not it does can be execution dependant, which makes this an exciting source of bugs.
while(1)
{
{
{// Here Scope Starts
int a=10;
a=5;
}// Here Scope Ends
}
}
The variable will logically be reallocated on the stack with each iteration -- in practice, the memory location will simply be reused. But note, in your trivial example, the value of "a" would never "visibly" hold the value of "5" when the loop returns to the declaration on the next iteration because it is explicitly initialized to "10" at the point it is declared. And if C# follows the same practice as Java, it would be implicitly reinitialized to a default value at that point if the compiler does not complain first that an uninitialized variable is being accessed if you do not initialize it yourself.
each iteration of while loop , you will define new variable a and value of "a" change also but if you loop finish by any way you will lose this variable (you can't use it even in same function)!!
a will be declared again.
usually you will define parameter as a in the loop if you do want it to reset each loop so you won't carry values from iteration to iteration.
while(1)
{
{
{
//Define a new `a`
int a=10;
a=5;
}
}
}
But if you wish to use the same parameter and value for all the iterations, you need to define it out side the loop:
int a=0;
while(1)
{
{
{
//`a` will count the number of iterations.
a = a + 1;
}
}
}