In the below code once I hit check_access as 0 how do I preserve the value and hit the
if condition below ($check_root && $check_access) . Break will only terminate the inner loop. But the other loops will continue as per me.
} else {
set check_access 0
break
}
}
}
if {$check_root && $check_access} {
set result 1
} else {
set result 0
}
The break and continue operations only go out one level of looping. If you need more than that, consider refactoring so that you can just return. Alternatively, try a custom exception in Tcl 8.6:
try {
foreach a $longList1 {
foreach b $longList2 {
if {[someCondition $a $b]} {
# Custom non-error exception
return -level 0 -code 123
}
}
}
} on 123 {} {
# Do nothing; we're out of the loop
}
break jumps to the end of the innermost loop only, and Tcl has no goto. But return, unless it's inside a catch or similar, exits a procedure which is like jumping to the end of it. So if you make the outermost loop the last command of the procedure (if your code is top-level, you have to put it in a procedure first to be able to use return), you can use return as a multi-break. Just move the commands after the loop out of the procedure and into the caller's code:
proc callMe {} {
foreach ... {
foreach ... {
if ... {
return
}
}
}
# move this code from here...
}
callMe
# ...to here
Another way is to put in extra tests:
set done 0
foreach ... {
foreach ... {
foreach ... {
if ... {
set done 1
break
}
}
if {$done} {break}
}
if {$done} {break}
}
Related
After watching carefully the following code I can't see why the compiler is warning me with "warning: control reaches end of non-void function".
bool Foam::solidMagnetostaticModel::read()
{
if (regIOobject::read())
{
if (permeabilityModelPtr_->read(subDict("permeability")) && magnetizationModelPtr_->read(subDict("magnetization")))
{
return true;
}
}
else
{
return false;
}
}
I can't see where is the problem, the else statement should care for returning false in every case which the first if is not true.
Trace the code path when regIOobject::read() is true, but either of permeabilityModelPtr_->read(subDict("permeability")) or magnetizationModelPtr_->read(subDict("magnetization")) is false. In that case, you enter the top if block (excluding the possibility of entering its attached else block), but then fail to enter the nested if block:
bool Foam::solidMagnetostaticModel::read()
{
if (regIOobject::read())
{
// Cool, read() was true, now check next if...
if (permeabilityModelPtr_->read(subDict("permeability")) && magnetizationModelPtr_->read(subDict("magnetization")))
{
return true;
}
// Oh no, it was false, now we're here...
}
else
{
// First if was true, so we don't go here...
return false;
}
// End of function reached, where is the return???
}
The minimalist fix is to just remove the else { } wrapping, so any fallthrough ends up at return false;:
bool Foam::solidMagnetostaticModel::read()
{
if (regIOobject::read())
{
// Cool, read() was true, now check next if...
if (permeabilityModelPtr_->read(subDict("permeability")) && magnetizationModelPtr_->read(subDict("magnetization")))
{
return true;
}
// Oh no, it was false, now we're here...
}
// Oh, but we hit return false; so we're fine
return false;
}
Alternatively, avoid specifically mentioning true or false at all, since your function is logically just a result of anding three conditions together:
bool Foam::solidMagnetostaticModel::read()
{
// No need to use ifs or explicit references to true/false at all
return regIOobject::read() &&
permeabilityModelPtr_->read(subDict("permeability")) &&
magnetizationModelPtr_->read(subDict("magnetization"));
}
The nested if is the problem.
When that branch is not taken, there is no other paths to take
the else statement should care for returning false in every case which the first if is not true.
Correct, but what if the first if condition is true, but the second if condition is not?
That is: What if regIOobject::read() returns true, but permeabilityModelPtr_->read(subDict("permeability")) returns false?
Then the flow of control enters the first if block, does not return, but does not enter the else block (because the first condition was true), so it just falls off the end of the function without hitting a return statement.
If you want the else { return false; } part to apply to either condition, you could just naively copy/paste it:
if (COND1) {
if (COND2) {
return true;
} else {
return false;
}
} else {
return false;
}
But that's quite a bit of code duplication. A better solution is to replace the nested if by a single condition:
if (COND1 && COND2) {
return true;
} else {
return false;
}
There's still some duplication: Both branches consist of a return statement followed by some expression.
We can factor out the common parts (return) and push the condition into the expression:
return COND1 && COND2 ? true : false;
But ? true : false is redundant: If the condition is true, evaluate to true, else evaluate to false? Well, that's just what the condition itself does:
return COND1 && COND2;
Or with your concrete expressions:
return regIOobject::read()
&& permeabilityModelPtr_->read(subDict("permeability"))
&& magnetizationModelPtr_->read(subDict("magnetization"));
I wounder if there is some construction convention for constructing method with multiple if's. Most of the time before you fire your method you have to check input arguments and other things, eg. is not nullptr, is > 0, is != -1 etc. Sometimes you cannot check this in one if and as a result you have something like this:
if(arg != nullptr)
{
if()
{
if()
{
if()
{
/*actual code here*/
}
else
{
}
}
else
{
}
}
else
{
/* other error message like "License check error: wrong key!" */
}
}
else
{
/* wrong input args! */
}
Good convention is that your line has less than 80 characters which gives us less space for actual code. Code is getting more and more unreadable.
You could return early in the case of issues, or throw an exception:
if(arg == nullptr) {
log("arg was null, not doing anything");
return;
}
//if the user forgot to make the toast, we can do it for them
if(forgotToMakeToast) {
makeToast();
}
if(ranOverDog) {
//we can't continue if the user ran over our dog, throw an exception
throw too_angry_exception;
}
//actual code
This makes your code structure more obvious by relating the error handling to the error checking by locality.
What I usually do is something like this:
if(arg == nullptr)
{
/* wrong input args! */
return;
}
if()
{
/* other error message like "License check error: wrong key!" */
return;
}
...
/*actual code here*/
Then you have all your error "ifs" and error handling in one place, and the actual function code at the end, nicely separated.
When you have too many sub-levels of if, while, for in a function, it is a sign that the function should be split into 2 or more separate functions. Depending on specific code it could look something like this:
public void MyClass::Run(arg)
{
if(arg != nullptr)
{
if()
{
RunActualCode()
}
else
{
/* other error message like "License check error: wrong key!" */
}
}
else
{
/* wrong input args! */
}
}
private void MyClass::RunActualCode(...)
{
if()
{
if()
{
/*actual code here*/
}
else
{
}
}
else
{
}
}
There are many recommendation about this, for example:
Rec 4.7 Do not have too complex functions.
Everyone that has ever had to take over code written by someone else
knows that complex code is hard to maintain. There are many ways in
which a function can be complex, such as the number of lines of code,
the number of parameters, or the number of possible paths through a
function. The number of possible paths through a function, which is
the result from the use of many control flow primitives, is the main
reason to why functions are complex. Therefore you should be aware of
the fact that heavy use of control flow primitives will make your code
more difficult to maintain.
http://www.tiobe.com/content/paperinfo/CodingStandards/hem/industrial/bookindex.htm
Limiting complexity during development
Your original construction could be written like this:
do
{
if(nullptr == arg) // Note: *negate* your original conditions!
{
/* wrong input args! */
break;
}
if(...)
{
/* other error message like "License check error: wrong key!" */
break;
}
if(...)
{
...
break;
}
if(...)
{
...
break;
}
/*actual code here*/
} while (0);
Advantages:
no nested ifs;
use break instead of goto to jump out of the whole block;
the logic is clearer, and more maintainable: if you want to add a check guard, just append one more if(...){...; break;};
Disadvantages:
do-while(0) looks a bit strange;
you should negate all your original conditions, e.g. if(cond) => if(!cond), which may affect the code clarity;
how can i exit from nested while() or for() without goto?
for example if i use three loops like below in a function:
void myfun(){
for (;;)
{
while( true )
{
for (;;)
{
//what is the exit code of all loop() from here?
}
}
}
}
using break; only can exit from one loop,
but how can i exit all loops ?
the loops can be limited by counter or unlimited.
I personally would rewrite the code so that you don't have a nested loop in the first place. Something like this:
bool myFun2
{
for (;;)
{
if(something) return true;
}
// If the loop isn't "forever", return false here?
}
bool myFun1()
{
while( true )
{
if (myFun2()) return true;
}
// return false here if needed.
}
void myfun()
{
for (;;)
{
if(myFun1()) break;
}
}
This becomes much easier to follow than trying to figure out which conditions some exitLoop variable gets set, for example.
You can't, you need another break at while context or change yours loops usign a variable as a exit flag:
bool exit = false;
for (;;){
while (!exit){
for (;;){
exit = true;
break;
}
}
if (exit) break;
}
An so on for as many loop do you have in your code
If you want to jump out of the function that is leave the function then you should use return. However if you want to just jump off the nested loops & not out of the function then you can throw an exception. This method will help you from breaking the code into several functions as some have done. However exceptions are meant for library designers & we should avoid using them too much. Personally speaking using goto is the best thing in this case but as you asked against it, hence I'm saying so. Well then your code will look like this :-
void myfun()
{
try
{
for (;;)
{
while( true )
{
for (;;)
{
if (/*some condition*/)
throw false;
}
}
}
}
catch (bool)
{
cout<<"caught";
}
// do stuffs if your code is successful that is you don't break out
}
I have this C++ program with the following general structure
1st while (condition A == true)
//some code for 1st loop
2nd while (condition B == true)
//some code for 2nd loop
try
//some code for try
catch
//condition B == false (supposed to leave 2nd loop and go back to first loop)
I want it to get out of 2nd loop when there's an exception and go back to 1st loop until condition B is tue again. As described above it doesn't work as I expect. What seems to be happening is that code gets stuck in catch and never leaves it.
How can I arrange it to make it work as I need?
Note: condition A is never false.
add the break keyword to the catch
Also notice that you have b == false;
That is checking that b is equal to false, not setting b = false.
bool flag1 = true, flag2 = true;
while (flag1)
{
// some work so that flag2 == true
while (flag2)
{
try
{
}
catch (...) // any exception happens
{
break;
}
}
}
1st while (condition A == true)
//some code for 1st loop
2nd while (condition B == true)
//some code for 2nd loop
try
//some code for try
catch
{
//condition B == false (supposed to leave 2nd loop and go back to first loop)
break ;
}
Notice: Please do not use, even in examples, things like condition A == true. It is better to use while (condition A).
You can call break within the catch block to escape the second loop:
void foo(void) {
bool A(true);
while (A) {
bool B(doSomething());
while (B) {
try {
B = doSomethingElseThatMayThrow();
} catch (...) {
break;
}
}
}
}
Alternatively, you could place the second loop inside the try block:
void foo(void) {
bool A(true);
while (A) {
bool B(doSomething());
try {
while (B) {
B = doSomethingElseThatMayThrow();
}
} catch (...) {}
}
}
The problem: I need to make a script or an expression that that doesn't break if somewhere on callstack is a function with a specific name.
Specific question: How can I get functions on callstack to a list of strings ?
Example:
Module!MyFunctionWithConditionalBreakpoint
Module!Function1
Module!Function2
Module!Function3
Module!MyFunctionWithConditionalBreakpoint
Module!Function1
Module!ClassA:MemberFunction
Module!Function3
I want Module!MyFunctionWithConditionalBreakpoint to break only if the call cames from Module!ClassA:MemberFunction
I need this in unmanaged code. Managed solution is something like
System.Diagnostics.StackTrace().ToString().Contains("YourMethodName")
In WinDbg you may set a conditional breakpoint using special $spat function:
bp Module!MyFunctionWithConditionalBreakpoint "r $t0 = 0;.foreach (v { k }) { .if ($spat(\"v\", \"*Module!ClassA:MemberFunction*\")) { r $t0 = 1;.break } }; .if($t0 = 0) { gc }"
In pseudo-code it will be something like:
t0 = 0
foreach (token in k-command result) {
if (token.contains("Module!ClassA:MemberFunction")) {
t0 = 1
break
}
}
if (t0 == 0) {
// continue execution
} else {
// break into the debugger
}
Why not set a breakpoint on entering Module!ClassA:MemberFunction to enable a breakpoint for Module!MyFunctionWithConditionalBreakpoint and upon leaving Module!ClassA:MemberFunction disabling it?