Stuck in a loop after switch in c - c

while (1)
{
c = getchar();
switch(state)
{
case 0:
if((GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == Bit_SET))
{
state=1;
}
if ( c=='p')
{
state = 2;
}
break;
case 1 :
if((GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) != Bit_SET))
{
state = 0;
}
break;
case 2:
iprintf("%s",led_name_arr[i]);
if (c=='r')
{
state=0;
}
break;
}
}
I want to print the printf and then reach state2 .. how can this be achieved .below is what i have tried and where i am stuck .
psuedocode:
if ( c==P)
{
printf(" hi");
state 2;
}
** in this case the printf statement does not get executed **
or
case 2:
iprintf("%s",led_name_arr[i]);
if (c=='r')
{
state=0;
}
break;
** in this case the printf statement keeps printing in a loop **
i dont want the while loop to stop , in a continuous loop i want case 0 keeps working , but when it get the input p .. it pauses and executes the printf ... and waits till it gets a r to resume case 0 .... Thus the program never halts but waits to either get "P" or "R" to execute each case... I hope i make sense
Any help will be appreciated .

Your breaks are breaking out of the switch ... case not the while. You'll need to use some kind of boolean flag to break out of the outer loop, e.g.:
bool someflag = true;
while(someflag){
switch(something){
case a:
someflag = false; // set the flag so we break out of the loop
break; // break out of the switch-case so we don't enter case b
case b:
// do something else
break;
}
}
-------- EDIT, because I misunderstood the question ------------
I think you need an extra state in your logic, right now (ignoring state 1), you have two states:
Wait for a p, when you get one, goto 2.
printf for each character until you get an r, then goto 1
What you want is:
Wait for a p, when you get one, goto 2.
Do a printf, then goto 3.
Wait for an r, when you get one, goto 1.

i am not sure what you are asking but i m pretty sure what you want in case 2 is something like this:
case 2:
iprintf("%s",led_name_arr[i]);
while(c!='r')
{
c = getchar();
}
state=0;
break;

You've created an infinite loop with the while (1) statement that has no possible exit. The break statements within the switch apply to the switch statement, not the while loop. You need another break statement outside the switch.

well,
initialize state to 0
compile and run the program
first time enter p // here state =2
then enter r // here state = 0
....continue in a loop due to while(1)

Because you are not breaking the while(1) loop. Use one more break for while loop.

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
}

I am trying to 'break' the loop, but the function just keep looping [duplicate]

I'm writing some code that looks like this:
while(true) {
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
break; // **HERE, I want to break out of the loop itself**
}
}
Is there any direct way to do that?
I know I can use a flag, and break from the loop by putting a conditional break just after the switch. I just want to know if C++ has some construct for this already.
You can use goto.
while ( ... ) {
switch( ... ) {
case ...:
goto exit_loop;
}
}
exit_loop: ;
An alternate solution is to use the keyword continue in combination with break, i.e.:
for (;;) {
switch(msg->state) {
case MSGTYPE:
// code
continue; // continue with loop
case DONE:
break;
}
break;
}
Use the continue statement to finish each case label where you want the loop to continue and use the break statement to finish case labels that should terminate the loop.
Of course this solution only works if there is no additional code to execute after the switch statement.
Premise
The following code should be considered bad form, regardless of language or desired functionality:
while( true ) {
}
Supporting Arguments
The while( true ) loop is poor form because it:
Breaks the implied contract of a while loop.
The while loop declaration should explicitly state the only exit condition.
Implies that it loops forever.
Code within the loop must be read to understand the terminating clause.
Loops that repeat forever prevent the user from terminating the program from within the program.
Is inefficient.
There are multiple loop termination conditions, including checking for "true".
Is prone to bugs.
Cannot easily determine where to put code that will always execute for each iteration.
Leads to unnecessarily complex code.
Automatic source code analysis.
To find bugs, program complexity analysis, security checks, or automatically derive any other source code behaviour without code execution, specifying the initial breaking condition(s) allows algorithms to determine useful invariants, thereby improving automatic source code analysis metrics.
Infinite loops.
If everyone always uses while(true) for loops that are not infinite, we lose the ability to concisely communicate when loops actually have no terminating condition. (Arguably, this has already happened, so the point is moot.)
Alternative to "Go To"
The following code is better form:
while( isValidState() ) {
execute();
}
bool isValidState() {
return msg->state != DONE;
}
Advantages
No flag. No goto. No exception. Easy to change. Easy to read. Easy to fix. Additionally the code:
Isolates the knowledge of the loop's workload from the loop itself.
Allows someone maintaining the code to easily extend the functionality.
Allows multiple terminating conditions to be assigned in one place.
Separates the terminating clause from the code to execute.
Is safer for Nuclear Power plants. ;-)
The second point is important. Without knowing how the code works, if someone asked me to make the main loop let other threads (or processes) have some CPU time, two solutions come to mind:
Option #1
Readily insert the pause:
while( isValidState() ) {
execute();
sleep();
}
Option #2
Override execute:
void execute() {
super->execute();
sleep();
}
This code is simpler (thus easier to read) than a loop with an embedded switch. The isValidState method should only determine if the loop should continue. The workhorse of the method should be abstracted into the execute method, which allows subclasses to override the default behaviour (a difficult task using an embedded switch and goto).
Python Example
Contrast the following answer (to a Python question) that was posted on StackOverflow:
Loop forever.
Ask the user to input their choice.
If the user's input is 'restart', continue looping forever.
Otherwise, stop looping forever.
End.
Code
while True:
choice = raw_input('What do you want? ')
if choice == 'restart':
continue
else:
break
print 'Break!'
Versus:
Initialize the user's choice.
Loop while the user's choice is the word 'restart'.
Ask the user to input their choice.
End.
Code
choice = 'restart';
while choice == 'restart':
choice = raw_input('What do you want? ')
print 'Break!'
Here, while True results in misleading and overly complex code.
A neatish way to do this would be to put this into a function:
int yourfunc() {
while(true) {
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
return;
}
}
}
Optionally (but 'bad practices'): as already suggested you could use a goto, or throw an exception inside the switch.
AFAIK there is no "double break" or similar construct in C++. The closest would be a goto - which, while it has a bad connotation to its name, exists in the language for a reason - as long as it's used carefully and sparingly, it's a viable option.
You could put your switch into a separate function like this:
bool myswitchfunction()
{
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
return false; // **HERE, I want to break out of the loop itself**
}
return true;
}
while(myswitchfunction())
;
Even if you don't like goto, do not use an exception to exit a loop. The following sample shows how ugly it could be:
try {
while ( ... ) {
switch( ... ) {
case ...:
throw 777; // I'm afraid of goto
}
}
}
catch ( int )
{
}
I would use goto as in this answer. In this case goto will make code more clear then any other option. I hope that this question will be helpful.
But I think that using goto is the only option here because of the string while(true). You should consider refactoring of your loop. I'd suppose the following solution:
bool end_loop = false;
while ( !end_loop ) {
switch( msg->state ) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
end_loop = true; break;
}
}
Or even the following:
while ( msg->state != DONE ) {
switch( msg->state ) {
case MSGTYPE: // ...
break;
// ... more stuff ...
}
There's no C++ construct for breaking out of the loop in this case.
Either use a flag to interrupt the loop or (if appropriate) extract your code into a function and use return.
No, C++ does not have a construct for this, given that the keyword "break" is already reserved for exiting the switch block. Alternatively a do..while() with an exit flag could suffice.
do {
switch(option){
case 1: ..; break;
...
case n: .. ;break;
default: flag = false; break;
}
} while(flag);
You could potentially use goto, but I would prefer to set a flag that stops the loop. Then break out of the switch.
Why not just fix the condition in your while loop, causing the problem to disappear?
while(msg->state != DONE)
{
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
// We can't get here, but for completeness we list it.
break; // **HERE, I want to break out of the loop itself**
}
}
It amazes me how simple this is considering the depth of explanations... Here's all you need...
bool imLoopin = true;
while(imLoopin) {
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
imLoopin = false;
break;
}
}
LOL!! Really! That's all you need! One extra variable!
I think;
while(msg->state != mExit)
{
switch(msg->state)
{
case MSGTYPE: // ...
break;
case DONE:
// ..
// ..
msg->state =mExit;
break;
}
}
if (msg->state ==mExit)
msg->state =DONE;
I got same problem and solved using a flag.
bool flag = false;
while(true) {
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
flag = true; // **HERE, I want to break out of the loop itself**
}
if(flag) break;
}
Because the switch uses the break to break out from the switch (not from the while(1)), it needs the goto-statement:
while(1) {
switch (*p) {
case ' ':
p++;
break;
case '\n':
p++; *s=p; return(i);
case '\0':
*s=p; return(i);
default:
token[i]=p;
i++;
p++;
goto ex1;
};
};
ex1:
I can't add multiple case to same line like:
case ' ','\t':
it would be
case ' ': case '\t':
That's why maybe the break used here...
It looks the most frequent cases should be placed at the top of the list to make the program run faster.
It may not have parallel execution for searching the different cases.
It is possible that the standard c then has missing some methods about this switching:
https://blog.hackajob.co/better-c-switch-statements-for-a-range-of-values/
=> allows you to use the <, >, <=, and >= operators in a switch expression
I was thinking that it should be (if c-language syntax changed) like:
switch (c) {
case >= 5:
... op1
endcase;
case == 1:
case == 3:
... op2
endcase;
default:
...
};
where op2 is executed when c is equal to 1 or 3 and when c is larger than or equal to 5 op1 is executed.
Because comparison for equal or larger/smaller than would occur easily in similar manner.
while(1) {
switch (c) {
case >= 2:
... op1
case <= 5:
... op2
break;
default:
...
};
};
this case op1 is executed for c larger than 2 and op2 executed for 2<=c<=5 and break exits it from while-loop.
The simplest way to do it is to put a simple IF before you do the SWITCH , and that IF test your condition for exiting the loop .......... as simple as it can be
The break keyword in C++ only terminates the most-nested enclosing iteration or switch statement. Thus, you couldn't break out of the while (true) loop directly within the switch statement; however you could use the following code, which I think is an excellent pattern for this type of problem:
for (; msg->state != DONE; msg = next_message()) {
switch (msg->state) {
case MSGTYPE:
//...
break;
//...
}
}
If you needed to do something when msg->state equals DONE (such as run a cleanup routine), then place that code immediately after the for loop; i.e. if you currently have:
while (true) {
switch (msg->state) {
case MSGTYPE:
//...
break;
//...
case DONE:
do_cleanup();
break;
}
if (msg->state == DONE)
break;
msg = next_message();
}
Then use instead:
for (; msg->state != DONE; msg = next_message()) {
switch (msg->state) {
case MSGTYPE:
//...
break;
//...
}
}
assert(msg->state == DONE);
do_cleanup();
while(MyCondition) {
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
MyCondition=false; // just add this code and you will be out of loop.
break; // **HERE, you want to break out of the loop itself**
}
}
If I remember C++ syntax well, you can add a label to break statements, just like for goto. So what you want would be easily written:
while(true) {
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
break outofloop; // **HERE, I want to break out of the loop itself**
}
}
outofloop:
// rest of your code here
while(true)
{
switch(x)
{
case 1:
{
break;
}
break;
case 2:
//some code here
break;
default:
//some code here
}
}

Is there any better implementation for this switch case construct?

I'm working on an embedded system where a register hast to be accessed and after that to be incremented to achieve the result I'm looking for, since the machine is notifying and configured to react on my access and changing or not changing the flag. So the switch's argument has to be kept as it is, since it would otherwise change the behaving of the embedded system.
But there may occur a situation where I don't want to get any of the cases get invoked. But I still need to acces and increment the argument of the switch.
(More indepth I'm converting a sequence of analog values to digital values conversions step by step. The index is used to stay synchronized with the current conversion and relating it with the corresponding case to handle the figure correct. There may occur a state in which the index desynchronisizes to the current conversion so the sequence of conversions must be run through without any of the cases getting invoked (to prevent setting wrong data) untill the sequence is finished and the resynchroinisation can get performed)
The way I'm currently doing this is this:
switch (RunIndex++)/*RunIndex may only be accessed one time per execution
of this construct and has to be incremented in the same step. thats given.*/
{
if (RunIndexSyncedWithADCensured == false)
{
break;
}
case 0:
Case0RelatedData = SomeOperationsForCase0(RawData);
break;
case 1:
Case1RelatedData = SomeOperationsForCase1(RawData);
break;
case 2:
Case2RelatedData = SomeOperationsForCase2(RawData);
break;
default:
RunIndex = 0;
break;
}
This construct does the job but it looks like it is a bit controversial and I don't feel well by considering about committing this into productinal code.
So is there a better looking way to achieve the same, without the need of additional variables or assignements?
note:
Also it may be relevant, that this is in the first part of a interupt function consisting of 2 parts.
The first part handles what has to happen if() a conversion is finished. The second part, what has additional to be done if() this conversion also ended the sequence. So it is no option to simply return from the function without getting into the second part. and there is currently no loop structure where an if(...)break; may break out. (What is also the reason why I'm putting the if inside the switch scope, as it is at least by standard a valid way to break out.)
Firstly, the if() inside switch() will never be executed.
Consider the below code snippet:
#include <stdio.h>
int main(int argc, char *argv[])
{
int i = 2;
switch(i) {
if (i == 2) {
printf("I M HERE\n");
}
case 1:
printf("1\n");
break;
case 2:
printf("2\n");
break;
default:
printf("default\n");
break;
}
return 0;
}
For your code: you expect the string I M HERE to be printed. But that is not the case.
The output for the above code snippet is:
2
No statements before case/default(switch constructs): is executed inside switch
Now to answer for
I don't want to get any of the cases get invoked. But I still need to acces and increment the argument of the switch
Just move the if() outside to the switch().
if (RunIndexSyncedWithADCensured) {
switch (RunIndex++) {
case 0:
Case0RelatedData = SomeOperationsForCase0(RawData);
break;
/* Other cases here */
default:
RunIndex = 0;
break;
}
} else
RunIndex++;
Why not save the value first and then increment it and use the saved value in the switch? By the way this also includes two accesses, first to read the value from RunIndex and the second to increment it.
int runIndex = (RunIndex++);
if (RunIndexSyncedWithADCensured )
{
switch (runIndex)/*RunIndex may only be accessed one time per execution
of this construct and has to be incremented in the same step. thats given.*/
{
case 0:
Case0RelatedData = SomeOperationsForCase0(RawData);
break;
case 1:
Case1RelatedData = SomeOperationsForCase1(RawData);
break;
case 2:
Case2RelatedData = SomeOperationsForCase2(RawData);
break;
default:
RunIndex = 0;
break;
}
}
Since you are using adjacent index numbers, you could make an array of function pointers to replace the switch. That's what the optimizer will turn the switch into anyhow. So instead of your obscure switch, you get this:
if (RunIndexSyncedWithADCensured)
{
SomeOperationsForCase[RunIndex](RawData);
}
RunIndex++;
if (RunIndex > MAX)
{
RunIndex = 0;
}
Completely unrelated to the switch statement design: in case RunIndex is a sensitive volatile variable such as some hardware register, then you shouldn't use it directly in any form of computations. Make a copy of it:
volatile int RunIndex;
...
int index = RunIndex; // read from RunIndex
if (RunIndexSyncedWithADCensured)
{
SomeOperationsForCase[index](RawData);
}
index++;
if (index > MAX)
{
index = 0;
}
RunIndex = index; // write to RunIndex
This is standard practice for all such volatile variables.

What is the priority with nested case, for and if loop?

I have a program similar to this:
switch(x)
{ case 1:
for(i=0; i<10; i++)
{
if ((i==3) || (i==4) || (i==5) || (i==6) || (i==7))
{
if (foobar[i])
break; // i am talking about this break
}
}
...further program
break; /not this break
if foobar[i] is true, would the program break out of the case label or the for loop?
The break follows a LIFO type nature, that is, the last break will come out of the first control structure. So, the break that you chose would break out of the for-loop, not the case.
The for loop.
Please see: break Statement (C++):
The break statement ends execution of the nearest enclosing loop or
conditional statement in which it appears. Control passes to the
statement that follows the ended statement, if any.
break will only break out of the for loop. If you have nested statements, it will only break out one level
Is the for loop. The break will bubble up until find the first for, while or a switch.
So you can just write your program like this:
switch(x){
case 1:
int loopBreaked = 0; //If you want to know if the loop has breaked
for(int i=0; i<10; i++) {
if (i <= 7 && i >= 3 && foorbar[i]) {
loopBreaked = 1;
break; //breaks the loop
}
}
break; //breaks the switch
}
How about:
for(i=3; i<=7 && !foobar[i]; i++) {}
For the sake of completeness, break will break out of the innermost statement of the type for do while, or switch. There is no need to break out of an if statement, since simply ending the code block will do the same job.
Your break will break the for loop. And the break you using later, break the switch. You can consider this code sample:
for(int i=0;i<len;i++)
{
for(int j=0;j<len;j++)
{
//statements
break;
}
//statements
break;
}
the break inside the inner loop break the inner loop and the following break statement will break the outer loop. In your code sample, the break you noticed is inside the for loop. So, the for loop will break.

Switch Statement with three cases in C. Third Case is not running properly

below is a do-while loop that I coded. When I run it, the first two cases do their job and run perfectly. However. the third case is supposed to quit the program but instead it does nothing and just goes back to the series of printf statements in the beginning of the do-while loop. Any suggestions as to what I am doing wrong?
do
{
printf("Choose one of the following (1, 2, or 3) \n");
printf("1. Find GCD of two positive integers\n");
printf("2. Sort 3 integers in the ascending order\n");
printf("3. Quit the program\n");
printf("Please enter your choice: ");
scanf("%d", &option);
switch (option)
{
case 1:
gcd(p, q);
printf("\nDo you want to try again? Say Y(es) or N(o): ");
getchar();
response = getchar();
break;
case 2:
sort(p, q, r);
printf("\nDo you want to try again? Say Y(es) or N(o): ");
getchar();
response = getchar();
break;
case 3:
break;
}
}
while (response == 'Y' || response == 'y'); //Condition that will determine whether or not the loop continues to run.
printf("\nThank you for using my progam. Goodbye!\n\n");
return 0;
}
Response variable remains either Y or y and while loop never exits.
add
response = 'x'; //or something that isn't Y or y
before break; in case 3: option.
break statement exits from first iterative loop. In your case this is switch.
You must modify the response ( for example response =0).
case 3:
response=0; //different than 'Y' or 'y'
break;
Do it like this:
case 3:
return 0;
You also might consider eliminating case 3 and just do this:
default:
return 0;
in case 3,there is no input coming from the user, so the response variable remains true, try asking the user for an input or just put response = '(any letter that will make the condition false)'
break statement does not exit the program, it just exits from the switch block.
To exit :
1.
#include<stdlib.h>
And instead of break statement, use exit(0);
2.Change the case 3 as follows:
response='N';break;
The break statement in case 3 just exits from case 3 rather than from the program.
If you want to exit the program in case 3 then use the return statement.
return 0;
This statement exists the program rather than repeating the while loop.
You just interrupt the switch case.
How about using:
case 3:
return;
break;

Resources