how to get out of "if" loop in c? - c

if(turn==2)
{
if(forward) /*then what to do if this if comes true for coming out of outer loop*/
if(columnHead>0)
{
columnHead--;
addr[columnHead] |=1<<(rowHead-1);
}
else
{
columnHead =7;
addr[columnHead] |=1<<(rowHead-1);
}
if(rowTail!=(rowHead-1))
{
addr[columnHead+columnSize] &=~(1<<rowTail);
columnSize++;
rowTail++;
}
else
{
addr[columnTail] &=~(1<<columnTail);
if(columnTail==0)columnTail=8;
columnTail--;
}
back=1;
}
I want to come out of outer if loop if it satisfies condition if(forward)

You should create function of this code, and return from the block where the condition becomes true.

A standard idiom is to use while(true){/*your code here*/ break; } around the whole block and use break statements as appropriate which will take you to the end of the while brace. Just remember to include the final break or your program will loop.
Whatever you do, don't use a goto as they are considered very poor programming style.
Some folk, from the C days where while(true) would issue a compile warning, use for(;;) instead.
The odd thing is, thinking about this some more, you could use
do {
/*your code here, using break for premature exit*/
} while (false);
which doesn't need the final break. Only I've never seen this in production code.

I guess just putting an else in there will do what you want. Also, please put braces around big blocks - it makes the else part unambiguous.
if(turn==2)
{
if(forward) {
if(columnHead>0)
{
columnHead--;
addr[columnHead] |=1<<(rowHead-1);
}
else
{
columnHead =7;
addr[columnHead] |=1<<(rowHead-1);
}
} else {
if(rowTail!=(rowHead-1))
{
addr[columnHead+columnSize] &=~(1<<rowTail);
columnSize++;
rowTail++;
}
else
{
addr[columnTail] &=~(1<<columnTail);
if(columnTail==0)columnTail=8;
columnTail--;
}
back=1;
}
}
Version after the author's comment:
if(turn==2 && !forward) {
if(rowTail!=(rowHead-1))
{
addr[columnHead+columnSize] &=~(1<<rowTail);
columnSize++;
rowTail++;
}
else
{
addr[columnTail] &=~(1<<columnTail);
if(columnTail==0)columnTail=8;
columnTail--;
}
back=1;
}

You probably have to go the other direction, that means:
You don't want to check wether
if(forward) is true, but instead you want to do if(!forward).
Though you'd need to check what type forward is. I guess it's an integer though.

You can try giving the return 0; or return something; when you need to get out of the if, before that u may want to put the entire code in a c syntax function like-
(int)someFunction(int turn, int forward,
int columnHead, int rowHead, int rowTail, int columnTail)/*have all the arguments with proper types declaration*/{
//your code with return 0;
}.

why go into the "if" in the first place.
change the outter if to:
if(turn==2 && forward) //not sure if your logic required `forward` or `!forward` you were ambiguous
{
//...
}

Related

C "if" structure

I am learning C and my question might be silly but im confused.In a function like:
int afunction(somevariables)
{
if (someconditions)
{
do some stuff
return 1;
}
raise_error("error happened")
return 0;
}
My question is,if the if statement isnt meeted(success),then it will go to the raise_error ? in other words,does the raise_errors position act like if it was in a else statement,or its because you have to return something at the end(return 0)?or would it need a proper else statement?Basically im confused on how to make a propre if condition--if this condition isnt meet--then call raise_error.
thank you!
if the if statement isn't met (success), then it will go to the raise_error?
Yes. When if condition is not met, the control is passed to else branch if it exists; otherwise, the entire if statement is skipped.
in other words, does the raise_errors position act like if it was in a else statement?
In this case, the answer is "yes", but only because your if branch is structured in a way that terminates the function due to return statement at the end.
Without that return at the end the control would go to raise_error upon completion of the if branch.
in other words,does the raise_errors position act like if it was in a else statement
Yes. Unless raise_error() does something that exits process, the return 0 will be executed aferwards.
Basically im confused on how to make a propre if condition--if this condition isnt meet--then call raise_error.
The code is fine. But if it makes it easier to understand then you can use an else clause too.
Your code is functionally equivalent to:
int afunction(somevariables)
{
if (someconditions) {
do some stuff
return 1;
}
else {
raise_error("error happened")
return 0;
}
}
The code or line that is not under some condition will always be executed unless you get out of the code before getting to that unconditional line. You don't need else in this case since you return 1 and does not execute remaining lines

ternary conditional operator equivalent?

I'm trying to understand a while loop. I realize the basics of how ternary operators work, but have only used them in loo of if statements, not in a while loop.This piece of code is really throwing me off. What would be the equivalent to this statement if it was not shortened?
int runOnce=0;
while(runOnce=runOnce?((token=strtok(NULL," "))!=NULL):((token=strtok(strCopy," "))!=NULL)) {
....
This is a bit clearer in my opinion.
token = strtok (strCopy," ");
while (token!=NULL)
{
/* do stuff */
token = strtok (NULL," ");
}
Ok, let's go over it one by one. As you said you know the the basics to ternary operator, so I will get right to the problem. The code here :
// notice here I did not include the the assignment(=) operation and the variable before it
runOnce?((token=strtok(NULL," "))!=NULL):((token=strtok(strCopy," "))!=NULL)
which basically means
if(runOnce)
{
return ((token=strtok(NULL," "))!=NULL);
}
else
{
return ((token=strtok(strCopy," "))!=NULL);
}
This return value in turn will be save to the same variable runOnce
runOnce = // ternary condition mentioned above
So, finally if the variable runOnce is true, then the condition for while loop will be true
Updated:
To make the code more understandable you can do something like this
int runOnce=0;
while(conditionForWhileLoop(runOnce))
{
// ...
}
int conditionForWhileLoop(int runOnce)
{
if(runOnce)
{
return ((token=strtok(NULL," "))!=NULL);
}
else
{
return ((token=strtok(strCopy," "))!=NULL);
}
}
Of course there is a lot you can do than this, but it's a start

Readable conditional logic without unnecessary execution?

I'm trying to make the below code both readable and performant. I want to avoid any unnecessary call to getFlagB() while also not repeating anything. Below I have written two methods, each which satisfies exactly one of these criteria.
Assume getFlagB() cannot be altered in any way. Is there a way to meet both these requirements simultaneously in C, without creating additional flags?
// Method 1 - doesn't repeat code blocks but calls getFlagB even when it may not need to
void foo(int flagA)
{
int flagB;
getFlagB(&flagB);
if(flagA & flagB)
{
// Code block 0
}
else
{
// Code block 1
}
}
// Method 2 - doesn't no extra call to getFlagB, but repeats code block 1
void foo(int flagA)
{
int flagB;
if(flagA)
{
getFlagB(&flagB);
if(flagB)
{
// Code block 0
}
else
{
// Code block 1
}
}
else
{
// Code block 1
}
}
You can do this:
void foo(int flagA)
{
int flagB;
if(flagA)
{
getFlagB(&flagB);
if(flagB)
{
// Code block 0
return ;
}
}
// code block 1
}
Wrap getFlagB() in another method, then let the compiler sort it out for you.
int myGetFlagB() { int b; getFlagB(&b); return b; }
void foo(int flagA)
{
/* note: assume you mean && and not &, otherwise there is no way
* to short circuit - you always need to call getFlagB for a
* bitwise AND.
*/
if(flagA && myGetFlagB())
{
// Code block 0
}
else
{
// Code block 1
}
}
Compute the condition explicitly before the if.
_Bool condition = flagA;
if ( flagA ) { /* First decide what to do. */
_Bool flagB;
GetFlagB( & flagB );
condition = flagA && flagB; /* Prefer && over &. */
}
if ( condition ) { /* Then do it. */
Code1();
} else {
Code2();
}
If you really do not want to either encapsulate the getFlagB call or split your if, you can abuse the comma operator:
if(flagA && (getFlagB(&flagB), flagB)) {
Even though it does not look nice, it does precisely what you want.
EDIT
You can also do the following, so long as flagB is initialized to 0. This avoids a bug in the code I posted earlier that assumes the flags aren't modified inside code block 0, which can cause both code blocks 0 and 1 to execute. I'd recommend this new one only because you may at some point want to modify the flags inside foo():
int flagB = 0;
if (flagA)
getFlagB(&flagB);
if (flagA && flagB) {
// code block 0
} else {
// code block 1
}
Yes, flagA is tested twice. You have a ternary condition, but you're asking for a binary set of outcomes. Without using sequence points as one person mentioned, you must test twice or duplicate code or unnecessarily call a function or add extra function call overhead if flagA happens to be set.
They're all valid solutions IMHO. It is just a matter of how readable and how well performing you want the code to be, not to mention avoiding code duplication... Nobody likes that! :-)
Happy coding!
I cannot definitively say anything because I have not seen any actual code but it seems to me the flagA is irrelevant and can be ignored. While flagB must be evaluated because it is relevant and causes the code to change.
void foo()
{
getFlagB(&flagB)
if(flagB)
{
//Code 1
}
else
{
//Code 0
}
}
But I am assuming that you do not have an unnecessary flag in your program. So I would recommend doing the seconded one it is more efficient and elegant even thought it does not seem that way.

What does for(;;) mean?

I am confused by the for(;;) construct. I think it is a form of shorthand for an unlimited for loop but I can't be sure.
Here is the code:
for(;;)
{
//whatever statements
}
Your guess is correct; it's an infinite loop.* This is a common C idiom, although many people (including me) believe the following to be less cryptic:
while (1) { whatever statements; }
* It's infinite assuming there are no break/return/etc. statements inside the loop body.
It's an un-terminated loop. It is sometimes written with a while:
while (1)
or even better:
while (true)
I would expect to see a break or return inside any such loop, no matter whether it is written with for or while. There has to be some abnormal control flow or it really will be an infinite loop.
Yes, that's the for C syntax with blank fields for initialization expression, loop condition and increment expression.
The for statement can also use more than one value, like this sample :
for (i=0, j=100, k=1000; j < 500 || i<50 || k==5000; i++, j+=2, k*=6) {};
Maybe one step beyond in for understanding ? =)
Yes, the expressions in the for loop are just optional. if you omit them, you will get an infinite loop. The way to get out is break or exit or so.
This statement is basically equal to:
while(1) {}
There is no start, no condition and no step statement.
As I understand it, for(;;) creates a deliberate non-exiting loop. Your code is expected to exit the loop based on one or more conditions. It was once provided to me as a purer way to have a do while false loop, which was not considered good syntax. Based on the exit condition, it is easier to dispatch to a function to handle the result, failure, warning, or success, for example.
My explanation may not be the reason someone used that construct, but I'll explain in greater detail what it means to me. This construct may be someone's "Pure C" way of having a loop in which you can serially perform multiple steps, whose completion mean something like your application has performed all steps of initialization.
#define GEN_FAILURE -99
#define SUCCESS 0
/* perform_init_step1() and perform_init_step2() are dummy
place-holder functions that provide a complete example.
You could at least have one of them return non-zero
for testing. */
int perform_init_step1();
int perform_init_step2();
int perform_init_step1()
{
return 0;
}
int perform_init_step2()
{
return 0;
}
int ret_code = GEN_FAILURE;
for(;;)
{
if(SUCCESS != perform_init_step1())
{
ret_code = -1;
break;
}
if(SUCCESS != perform_init_step2())
{
ret_code = -2;
break;
}
break;
}
If part of the initialization fails, the loop bails out with a specific error code.
I arrived at using C having done a lot of firmware work, writing in assembly language. Good assembly language programmers taught me to have a single entry point and single exit. I took their advice to heart, because their creed helped them and me immensely when debugging.
Personally, I never liked the for(;;) construct, because you can have an infinite loop if you forget to break; out at the end.
Someone I worked with came up with do..until(FALSE), but the amount of proper C furvor this caused was not to be believed.
#define GEN_FAILURE -99
#define SUCCESS 0
/* perform_init_step1() and perform_init_step2() are dummy
place-holder functions that provide a complete example.
You could at least have one of them return non-zero
for testing. */
int perform_init_step1();
int perform_init_step2();
int perform_init_step1()
{
return 0;
}
int perform_init_step2()
{
return 0;
}
int ret_code = GEN_FAILURE;
do
{
if(SUCCESS != perform_init_step1())
{
ret_code = -1;
break;
}
if(SUCCESS != perform_init_step2())
{
ret_code = -2;
break;
}
}
until (FALSE);
This runs once, no matter what.

what should comment say when programmer is aware that it is bad style but necessary

In short I have code like this. I know its bad style but have given it a lot of thought and alternatives are worse. What should I say in a comment and where should I put it?
while(1)
{
if(x+y == z)//some comparison
{
…//do something
}
else
{
break;
}
}
Assuming that there is more code involved, so the obvious
while(x+y == z)
{
}
is not possible, you could use an additional variable to flag the loop status.
do_loop = 1;
while (do_loop)
{
// more code
do_loop = (x+y == z);
if (do_loop)
...
}
It offers more possibilities, esp. if deeper nesting is involved, since break; will only leave the innermost loop. Of course you should use a more exact naming for the condition instead of a generic do_loop, e.g. coords_are_equal.
If all alternatives are worse, including this, then just comment it as it is: "All alternatives are found to be worse than this."
You might consider rewriting this as
while (x+y == z) {
// Do something...
}

Resources