In the following code example - is it bad practice? Also why does the compiler go into the 2nd bracketed statement? I've oddly never experienced this before but it came up in an interview situation. I would have thought the 2nd bracketed segment would look for another conditional statement. The code is as follows:
if ( condition )
{
// some code
}
{
// some code
}
Thank you for any helpful explanations in advance.
You can make a block using { and } anywhere; it does not need to be attached to an if condition.
It can be useful for controlling an object's lifetime.
{
MyObject foo;
// ... do something with foo ...
} // MyObject just went out of scope, so its destructor is called
// foo is no longer defined
if ( condition )
{
// gets executed if condition == TRUE
}
{
// always gets executed, has nothing to do with previous if statement
int a = 42 ; //only exists inside brackets
}
Related
im a beginner starting to learn c++ i have a question.. Can i write scripts in do while loop i mean like this...
//you type do then like
do{
// your code here
}while(condition{ // <-- the question is here
then the code of the script
} ) closing Parenthesis and curly braces
yeah if you didn't understand that my question was that can i expand my condition in the while Parenthesis?? please answer because I'm learning C++ and I wanna improve.
The while condition takes an expression. That includes things like variables (foo), operators (1 + 2), and function calls. But it excludes things like if statements and additional loops. If you need to do something complicated inside of a while block, you should put it in a function.
do {
// ...
} while (should_continue(foo, bar));
bool should_continue(int foo, int bar) {
// ... complicated code goes here ...
}
Technically speaking, in C++11 and onward, you can create and evaluate a lambda in the same line, allowing arbitrary statements in expression context, but this is not very readable and should generally be a sign that your code needs to be split up into more functions.
// Don't do this; your coworkers will despise you.
do {
// ...
} while (([&]() {
// ... complicated code goes here ...
})());
Some non-portable compiler extensions will also allow the syntax you suggested in the question, where you can just throw braces { ... } with arbitrary statements in expression context. But, again, this is non-portable and not very readable code to begin with. So just write a function.
I am trying to understand a source code and i cannot figure out how the line for(;Q.size();) is meant to work. Could someone please simplify it for me ?
A for statement consists of three parts, separated by semicolons:
an init-statement
a condition
an iteration_expression
A for loop is equivalent to this code:
{
init_statement
while ( condition ) {
statement
iteration_expression ;
}
}
The init-statement and iteration_expression can be empty, but the semicolons between them are still required.
In your example, for(;Q.size();) would thus be equivalent to:
{
while ( Q.size() ) {
statement
}
}
Look at it this way:
for(<do nothing>;Q.size();<do nothing>) {//do something}
Now read the definition of the for loop and see that it fits perfectly.
As mentioned by others, essentially this becomes equivalent to while(Q.size())
It's a for loop which doesn't care about an incrementing index variable. As Blaze pointed out it's equivalent to a while loop.
for(;Q.size();)
{
// do something while Q is not empty
}
or equivalently
while(Q.size())
{
// do something while Q is not empty
}
One very experienced programmer wrote something like this:
#include <string>
using namespace std;
class Fraction
{
float nominator;
float denominator;
void load()
{
cin>>nominator; cin>>denominator;
if(denominator==0)
{
while(denominator==0)
{
cout<<"denominator can not be equal 0!"<<endl;
cin>>denominator;
}
}
}
};
I have no idea why there is an if statement. Is it really necessary?
In this particular example,
while(denominator==0)
{
cout<<"denominator can not be equal 0!"<<endl;
cin>>denominator;
}
would be exactly equivalent.
In the context you provided, nothing can tell us why someone would nest that loop in an useless if, but one could come up with explanations. In earlier version of that code, something could have been present inside the if block that changed the behavior of the program/function.
It also could be an innocent error.
Stroustrup's cat might have walked on their keyboard.
Is it really necessary?
No, it is not necessary.
The shown snippet is equivalent to a program where the if statement is replaced with the contained loop statement.
From this code:
if(denominator==0)
{
while(denominator==0)
{
cout<<"denominator can not be equal 0!"<<endl;
cin>>denominator;
}
}
I think if is only used for a teaching purpose to simply show that how flow will go to while after checking if condition. And how while loop will work further.
But if is not really required here.
This code do the same:
while(denominator==0)
{
cout<<"denominator can not be equal 0!"<<endl;
cin>>denominator;
}
Today, i spent 4 hours debugging a little mistake:
while (++i < nb); //Notice this semicolon that i put by mistake
{
do_stuff();
}
I didn't know why the do_stuff didn't execute enough times.
When I saw my mistake, I wondered: Why the hell would someone enclose codes into braces in the middle of a function??
Can someone have an explanation? Is that the way C languages evolved ? (I know the BNF of C contains some weird things due to retro compatibility reasons)
And do you think pre incrementation in a loop is a bad thing, that I should write like above instead?
while (i < nb)
{
do_stuff();
i += 1;
}
Why the hell would someone enclose codes into braces in the middle of a function??
Thats not a strange think at all, but it introduces a scope, as in the following example:
void foo () {
int a;
{ // start a new scope
int b = 1;
std::cout << b << std::endl;
} // end of scope, i.e. b is out of scope now
std::cout << a << std::endl;
std::cout << b << std::endl; // error: unknown variable b !!
double b = 0.0; // just fine: declares a new variable
}
You can use it to localize the accessability of variables inside functions. In the example b is a temporary and by putting its declaration inside a local scope I avoid spamming the function scope with variable names.
You might want to put all the logic inside the while and omit body intentionally. Some compilers will warn you about that, ie. clang:
main.cpp:18:17: warning: while loop has empty body [-Wempty-body]
while (++i < nb); //Notice this semicolon that i put by mistake
^
main.cpp:18:17: note: put the semicolon on a separate line to silence this warning
Introducing of local scopes like:
{
SomeClass aa;
// some logic
}
is also not uncommon, you might want, in above someone might want aa destructor to be called before the closing braces - ie. it will release some resource.
I believe most common use is together with RAII:
{
std::lock_guard<std::mutex> lock(mutex);
// code inside block is under mutex lock
}
// here mutex is released
Local scopes make sense to limit the life time and scope of objects. They are vital to switch/case statements:
switch (i){
case 1:
std::string s;
case 2:
//does s exist or not? depends on the value of i
}
C++ says this is straight-up illegal. To fix this you introduce a local scope:
switch (i){
case 1:
{
std::string s;
}//the lifetime of s ends here
case 2:
//s is inaccessible
}
Now s is limited to its scope and you solved the problem of s being sometimes defined.
You can add as many local blocks as you want, for example this is fine:
int main(){{{{{{{{{{
}}}}}}}}}}
{<statement>*} (* means zero or more) are code blocks in C/C++ and are treated as a single statement.
Statements are things like if (<expression>) <statement> (note: this is a recursive statement).
Another statement could be <expression>;.
Also {} generates a new scope.
This is also the reason why you can give multiple statements in an if statement.
If it helps, you can think of them as inline functions, with access to the current scope. (Not a correct way to view it, but close enough)
Look at #tobi303's answer for an example.
Why is this bad?
if (true)
int stuff = 10;
else
int stuff = 5;
printf("Stuff is %d\n",stuff);
Is it because of scope?
Yes. stuff only exists in the scope of the if and else blocks (where they are two different variables). You have to declare it outside the if-else to work.
int stuff;
if (true)
stuff = 10;
else
stuff = 5;
printf("Stuff is %d\n",stuff);
Your question is tagged both C and C++. The answer is different in the two languages.
In both C and C++, both branches of an if statement must be statements:
if (expression) statement else statement
where the statement is commonly a compound statement / block.
In C, a declaration is not a statement, so your code is simply a syntax error. Furthermore, the word true is not visible unless you have a #include <stdbool.h>. (For that matter, printf isn't visible unless you have a #include <stdio.h>, but since what you posted is a fragment of a larger program, we can probably assume that.)
You can make the if/else statement valid in both C and C++ by adding curly braces (which is generally good practice anyway):
if (true) {
int stuff = 10;
}
else {
int stuff = 5;
}
Now it becomes a bit clearer that you've declared two distinct variables, both named stuff. The scope of each of them ends at the end of the nearest enclosing block; in this case, that's the immediately following }:
if (true) {
int stuff = 10; // stuff is visible here
} // and now stuff is no longer visible
else {
int stuff = 5; // the other stuff is visible here
} // and now is no longer visible
After the end of the block, stuff isn't just no longer visible. It doesn't even exist, because it's reached the end of its lifetime. These are two different things: scope is a region of the program text, and lifetime is a subset of the execution time of the running program. stuff is only visible to code after its declaration and before the enclosing }. At run time, the object stuff exists only until execution reaches the closing }.
So yes, the main problem is scope. You have two distinct variables, both named stuff, and neither of them is visible to the printf call.
To fix this, as the other answers have already said, move the declaration of stuff so it's before the if/else statement, and assign to it rather than initializing it.
There are several other ways you can structure the code, depending on what you're trying to do (which is impossible to tell from the code you posted).
Define you code like this:
int stuff;
if (true)
stuff = 10;
else
stuff = 5;
printf("Stuff is %d\n",stuff);
You can read about c++ scope here.