Standard idiom for executing a while loop one more time - c

Is there a pattern in C to execute a while loop one more time.
Currently I'm using
while(condition) {
condition = process();
// process() could be multiple lines instead of a function call
// so while(process());process(); is not an option
}
process();
which is horrible if process is of multiple lines and not a single function call.
The alternative is
bool run_once_more = 1;
while(condition || run_once_more) {
if (!condition) {
run_once_more = 0;
}
condition = process();
condition = condition && run_once_more;
}
Is there a better way?
Note: A do while loop is not a solution as it is equivalent to
process();
while(condition){condition=process();}
I want
while(condition){condition=process();}
process();
Per requests, a bit more specific code.
I want to fill buffer from another_buffer and get
(indexof(next_set_bit) + 1) into MSB while maintaining both masks and pointers.
uint16t buffer;
...
while((buffer & (1 << (8*sizeof(buffer) - 1))) == 0) { // get msb as 1
buffer <<= 1;
// fill LSB from another buffer
buffer |= (uint16_t) (other_buffer[i] & other_buffer_mask);
// maintain other_buffer pointers and masks
other_buffer_mask >>= 1;
if(!(other_buffer_mask)) {
other_buffer_mask = (1 << 8*sizeof(other_buffer[0]) -1)
++i;
}
}
// Throw away the set MSB
buffer <<= 1;
buffer |= (uint16_t) (other_buffer[i] & other_buffer_mask);
other_buffer_mask >>= 1;
if(!(other_buffer_mask)) {
other_buffer_mask = (1 << 8*sizeof(other_buffer[0]) -1)
++i;
}
use_this_buffer(buffer);

Because it's not a very typical thing to do, it's unlikely that there is a standard idiom for doing this. However, I'd write the code like this:
for (bool last = 0; condition || last; last = !(condition || last)) {
condition = process();
}
The loop will execute as long as condition is true and then one more time, or zero times if condition is false when the loop begins. I interpret your question as meaning that that is the desired behavior. If not, and you always want the loop to execute at least once, then do...while is the idiom you seek.

What about this:
int done, condition = 1;
for (;;) {
...
done = !condition;
condition = process();
if (done) break;
...
}
I am not suggesting this is a standard idiom, just an ad hoc hack.

I'd use this:
bool done = false;
do {
if (!condition) done = true;
condition = process();
} while (!done);
A much less readable hack, assuming condition is not predefined:
for (bool condition=true, done=false;
!done && (condition || done = true);
) {
condition = process();
}

I've had this same issue and my solution is:
Only if you know for sure you want to run process() at least once:
while(1){
process();
if(!condition()) break;
/*The loop breaks before bad things happen*/
things_you_want_to_happen_only_while_condition_is_true();
}
If you are not sure:
if(condition()){ /*Same as before, but it checks first*/
while(1){
process();
if(!condition()) break;
/*The loop breaks before bad things happen*/
things_you_want_to_happen_only_while_condition_is_true();
}
}
For example:
/*A pointer that goes over the string T from right to left.
It prints "Yes" when pointing at the character 'O' and "No" when not*/
char T[] = {'O', 'V', 'E', 'R', 'F', 'L', 'O', 'W', 0};
char *P = &T[strlen(T)-1]; /*We want the pointer to start at the last character of T*/
while(1){
if(*P=='O') printf("Yes\n");
else printf("No\n");
if(P==&T[0]) break; /*When it reaches the beginning of T, it stops*/
/*We only want the pointer to go further back if it is not in the beginning of T.
That's because we don't know what's before in the memory.*/
P--;
}

Your code is way more advanced than my level, but I came to this question as I had a similar difficulty on a problem set (I wanted the function to execute one last time) and I solved it like this:
define check_value as type_required;
while (check_value)
{
check_value = additional_output_from_process;
condition = process();
}
Would something like that work? In my problem I'm just taking a modulus so I can just run the process twice, system overhead really isn't a consideration.
This works in my example but it might just be a specific use case? I don't know, I'm literally only 6 months into coding.
I think what I'm trying to say is: introduce an additional value, and set the logical test so that the function output (operation) additional value = true. Then set the value of the additional value before you evalutate the function. The result function output (operation) additional value then will only be set to true after the loop has already run again.

Related

How does the break statement work in this function? [duplicate]

Can you break out of an if statement or is it going to cause crashes? I'm starting to acquaint myself with C, but this seems controversial. The first image is from a book on C
("Head First C") and the snippet shows code written by Harvard's CS classes staff. What is actually going on and has it something to do with C standards?
breaks don't break if statements.
On January 15, 1990, AT&T's long-distance telephone system crashed, and 60,000 people lost their phone service. The cause? A developer working on the C code used in the exchanges tried to use a break to break out of an if statement. But breaks don't break out of ifs. Instead, the program skipped an entire section of code and introduced a bug that interrupted 70 million phone calls over nine hours.
for (size = 0; size < HAY_MAX; size++)
{
// wait for hay until EOF
printf("\nhaystack[%d] = ", size);
int straw = GetInt();
if (straw == INT_MAX)
break;
// add hay to stack
haystack[size] = straw;
}
printf("\n");
break interacts solely with the closest enclosing loop or switch, whether it be a for, while or do .. while type. It is frequently referred to as a goto in disguise, as all loops in C can in fact be transformed into a set of conditional gotos:
for (A; B; C) D;
// translates to
A;
goto test;
loop: D;
iter: C;
test: if (B) goto loop;
end:
while (B) D; // Simply doesn't have A or C
do { D; } while (B); // Omits initial goto test
continue; // goto iter;
break; // goto end;
The difference is, continue and break interact with virtual labels automatically placed by the compiler. This is similar to what return does as you know it will always jump ahead in the program flow. Switches are slightly more complicated, generating arrays of labels and computed gotos, but the way break works with them is similar.
The programming error the notice refers to is misunderstanding break as interacting with an enclosing block rather than an enclosing loop. Consider:
for (A; B; C) {
D;
if (E) {
F;
if (G) break; // Incorrectly assumed to break if(E), breaks for()
H;
}
I;
}
J;
Someone thought, given such a piece of code, that G would cause a jump to I, but it jumps to J. The intended function would use if (!G) H; instead.
This is actually the conventional use of the break statement. If the break statement wasn't nested in an if block the for loop could only ever execute one time.
MSDN lists this as their example for the break statement.
As already mentioned that, break-statement works only with switches and loops. Here is another way to achieve what is being asked. I am reproducing
https://stackoverflow.com/a/257421/1188057 as nobody else mentioned it. It's just a trick involving the do-while loop.
do {
// do something
if (error) {
break;
}
// do something else
if (error) {
break;
}
// etc..
} while (0);
Though I would prefer the use of goto-statement.
I think the question is a little bit fuzzy - for example, it can be interpreted as a question about best practices in programming loops with if inside. So, I'll try to answer this question with this particular interpretation.
If you have if inside a loop, then in most cases you'd like to know how the loop has ended - was it "broken" by the if or was it ended "naturally"? So, your sample code can be modified in this way:
bool intMaxFound = false;
for (size = 0; size < HAY_MAX; size++)
{
// wait for hay until EOF
printf("\nhaystack[%d] = ", size);
int straw = GetInt();
if (straw == INT_MAX)
{intMaxFound = true; break;}
// add hay to stack
haystack[size] = straw;
}
if (intMaxFound)
{
// ... broken
}
else
{
// ... ended naturally
}
The problem with this code is that the if statement is buried inside the loop body, and it takes some effort to locate it and understand what it does. A more clear (even without the break statement) variant will be:
bool intMaxFound = false;
for (size = 0; size < HAY_MAX && !intMaxFound; size++)
{
// wait for hay until EOF
printf("\nhaystack[%d] = ", size);
int straw = GetInt();
if (straw == INT_MAX)
{intMaxFound = true; continue;}
// add hay to stack
haystack[size] = straw;
}
if (intMaxFound)
{
// ... broken
}
else
{
// ... ended naturally
}
In this case you can clearly see (just looking at the loop "header") that this loop can end prematurely. If the loop body is a multi-page text, written by somebody else, then you'd thank its author for saving your time.
UPDATE:
Thanks to SO - it has just suggested the already answered question about crash of the AT&T phone network in 1990. It's about a risky decision of C creators to use a single reserved word break to exit from both loops and switch.
Anyway this interpretation doesn't follow from the sample code in the original question, so I'm leaving my answer as it is.
You could possibly put the if into a foreach a for, a while or a switch like this
Then break and continue statements will be available
foreach ([1] as $i) if ($condition) { // Breakable if
//some code
$a = "b";
// Le break
break;
// code below will not be executed
}
for ($i=0; $i < 1 ; $i++) if ($condition) {
//some code
$a = "b";
// Le break
break;
// code below will not be executed
}
switch(0){ case 0: if($condition){
//some code
$a = "b";
// Le break
break;
// code below will not be executed
}}
while(!$a&&$a=1) if ($condition) {
//some code
$a = "b";
// Le break
break;
// code below will not be executed
}

Loop through array, find zero, perform action, stop

I am relatively new at programming, and I'm having trouble figuring out how to loop through an array until the counter finds zero, and when it finds zero once, performs an action and exits the loop. Here is the loop I have so far:
for (int i = 0; i<13; i++)
{
if(pHand[i] == 0)
{
pHand[i] = deal(numArray);
printf("%d\n", i);
printHand(pHand, "Your");
}
}
Currently, this loops through the array until it finds zero, calls deal(), prints the value of pHand, and then loops back through the same sequence until i=0. Please help. I am completely stumped on how to fix this.
The break statement can be used to exit an enclosing loop (e.g., a while, do-while, or for) or switch.
for (int i = 0; i<13; i++)
{
if(pHand[i] == 0)
{
pHand[i] = deal(numArray);
printf("%d\n", i);
printHand(pHand, "Your");
break;
}
}
// code will continue executing here if the for loop condition becomes
// false (i is 13) or if the break statement is reached.
In your code, if you encountered ZERO value cell, you just call "deal" function and printf, but you don't exit the loop, your are continuing to the next iteration.
In order to exit the loop, add "break" statement in the "if" scope and you will go out the loop once you fulfill the condition.
Some consider break to be harmful. I've used it plenty, but some people have issues with it. If you wanted to avoid using break, you could do the following:
int i = 0;
char finished = 0;
while (i < 13 && !finished)
{
if(pHand[i] == 0)
{
pHand[i] = deal(numArray);
printf("%d\n", i);
printHand(pHand, "Your");
finished = 1;
}
i++;
}
You could also rework it to use do-while. Some would say that this kind of solution is a little nicer, semantically.

Switching the status of a state machine from inside a loop

I have an array (nchar[12]) and I wrote this code to print it as vertical columns composed of "X"'s.
I first wrote a version with an accumulator and a while-loop and it worked fine, but it only could print colums as long as a given limit.
Then I tried to write it as a state machine, but the output is just an endless series of blank spaces.
I declared status as an int and assigned a value of 1 to it, then:
while (status = 1) {
for (i = 1; i <= 12; ++i) {
status = 0;
if (nchar[i] > 0) {
printf(" X");
--nchar[i];
status = 1;
}
else
printf(" ");
}
It should stop when it doesn't find any value to print for the last processed line, but it just goes on forever and I don't understand why.
The loop never ends because = is the assignment operator not == which is the comparision operator. You probably want
while (status == 1)
Or simply
while (status)
instead of
while (status = 1)
Also if you have an array declared as
type nchar[12];
then the valid indices for it start from 0 and end at 11. So, your loop should start with i=0 and should loop until i<12 becomes false.

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.

Is it possible to execute both if and else part of an if --- else control statement? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Simultaneous execution of both if and else blocks
Is it possible to put some condition, so that both if and else part in an if ...else control statement can be executed without any warning or error ??
Do not use! ;-)
Yes, by forking.
if ( fork() ) {
printf("if\n");
}
else {
printf("else\n");
}
There are no real use cases to prefer the above code, unless it is for parallel execution.
No, there's no way to write a Schrödinger if clause.
You might be able to execute both with a goto, but it would never pass a code review.
Yes, it's possible:
#include <stdio.h>
#define else if (1)
int main(void)
{
int test = 1;
if (test == 1)
{
printf("if\n");
}
else
{
printf("else\n");
}
return 0;
}
#undef else
A note for newbies: Never do this in real life! Instead, think about your problem again...
What you probably wanted is :
#include <stdio.h>
int main(void)
{
int one_condition = 1;
int other_condition = 2;
if ((one_condition == 1) || (other_condition == 2))
{
printf("if\n");
}
if ((one_condition != 1) || (other_condition == 2))
{
printf("quasi-else\n");
}
return 0;
}
You can replace the else-path by having another if-clause with negated conditions. This gives you the possibility to override it with a second condition.
No, that is not possible (inside the same process).
Maybe you've misunderstood your problem.
If you want a code block to execute regardless of the condition, take it out of the if...else statement.
void foofunc(int n)
{
a = 44*n;
if(a == 484)
{
//do something
}
else
{
//do something if a DOES NOT equal 484
}
//do something regardless of the outcome of the test.
}
In this example, ridiculous though it is, the last line is outside the condition statement, so will execute whether a == 484 or not, which seems to me to be the same as making c trigger your else block regardless of the if test succeeds.
Of course, else blocks are not mandatory, so if you don't care what happens if your condition fails, then simply don't have an else block.
void foofunc(int n)
{
a = 44*n;
if(a == 484)
{
//do something
}
//do something regardless of the outcome of the test.
}
I assume you're trying to have both branches of this sort of statement execute?
Dim X As Boolean
X = False
If X = True Then
...
Else
...
End If
You could get it to execute using GoTo ... but that goes against good programming practice.
Dim X As Boolean
X = False
If X = True Then
...
Goto ElseStuff
Else
ElseStuff:
...
End If
Instead of that you should write separate procedures / functions to accomplish the behavior you'd like to have execute in both statements ... or simply put the code which should execute in all cases outside of the If block.
That would be functionally equivalent to using the GoTo, plus it makes it clear to anybody else.

Resources