ternary conditional operator equivalent? - c

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

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

Equivalent using for-loop instead do-while-loop

I was wondering instead of using a do-while loop, what is the equivalent for-loop or any other combination of loops in c?
Any sort of a loop can be constructed from a combination of an infinite "forever" loop, and a conditional break statement.
For example, to convert
do {
<action>
} while (<condition>);
to a for loop, you can do this:
for (;;) {
<action>
if (!<condition>) break;
}
You can use the same trick to convert a do/while loop to a while loop, like this:
while (true) {
<action>
if (!<condition>) break;
}
Moreover, the loop is not needed at all: any of the above can be modeled with a label at the top and a goto at the bottom; that is a common way of doing loops in assembly languages. The only reason the three looping constructs were introduced into the language in the first place was to make the language more expressive: the do/while loop conducts author's idea much better than any of the alternatives shown above.
There is no other loop that executes the loop content at least once, as do-while does. Of course you could emulate do-while with a flag and a while loop:
do {
A;
} while (B)
becomes
int flag=1;
while (flag || B) {
flag=0;
A;
}
but that's not really an alternative, it just obscures your original intent.
The following three loops are all equivalent:
#define FALSE (0)
#define TRUE (!(FALSE))
do
{
status = getStatus();
}
while(status == TRUE);
status = TRUE;
while(status == TRUE)
{
status = getStatus();
}
for(status = TRUE; status == TRUE; status = getStatus())
{
}

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.

how to get out of "if" loop in 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
{
//...
}

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.

Resources