break inside of case- statement inside of loop

Discussion in 'C Programming' started by Alexander Korsunsky, Feb 25, 2007.

  1. Hi!

    I have some code that looks similar to this:

    --------------------------------------------

    char array[10] = "abcdefghij";

    for (int i = 0; i < 10; i++)
    {
    switch (array)
    {
    case 'a':
    /* code */
    break;
    case 'b':
    /* code */
    break;
    case 'c':
    /* code */
    break;

    default:
    /* code */
    break;
    }

    }

    --------------------------------------------

    Is it possible to break out of the for loop from inside of one case-
    statement, or do I have to use a workaround?
    Alexander Korsunsky, Feb 25, 2007
    #1
    1. Advertising

  2. In article <>,
    Alexander Korsunsky <> wrote:
    >for (int i = 0; i < 10; i++)
    >{
    > switch (array)
    > {
    >[code snipped all up]
    > break;
    > }
    >
    >Is it possible to break out of the for loop from inside of one case-
    >statement, or do I have to use a workaround?


    break only gets you out of the smallest enclosing switch or loop.

    You could put another condition in the for:

    for (i = done = 0; i < 10 && !done; i++) {
    switch(array) {
    case 'a':
    done = 1;
    break; // or "continue" to get right out
    case 'b':
    break;
    }
    }

    Or you could use goto:

    for (i = 0; i < 10; i++) {
    switch(array) {
    case 'a':
    goto done;
    case 'b':
    break;
    }
    }
    done:

    -Beej--4am...hopefully I didn't screw that answer up too bad.
    Beej Jorgensen, Feb 25, 2007
    #2
    1. Advertising

  3. Alexander Korsunsky

    Bill Pursell Guest

    On Feb 25, 11:16 am, Alexander Korsunsky <>
    wrote:

    >
    > char array[10] = "abcdefghij";


    It's unfortunate that this doesn't generate a
    compiler warning in the same way that
    int array[2] = { 1, 2, 3}; does.


    >
    > Is it possible to break out of the for loop from inside of one case-
    > statement, or do I have to use a workaround?


    There are at least 3 obvious ways:
    1) increment the index to cause your condition on the
    for loop to terminate the loop (a workaround.)
    2) goto
    3) fix the loop condition to more accurately reflect
    whatever it is you are testing for. (Probably
    the correct solution.)

    There is no "break 3" type syntax in C, however.

    --
    Bill Pursell
    Bill Pursell, Feb 25, 2007
    #3
  4. Alexander Korsunsky

    Bob Guest

    On Sun, 25 Feb 2007 12:16:06 +0100, Alexander Korsunsky
    <> wrote:

    >Hi!
    >
    >I have some code that looks similar to this:
    >
    >--------------------------------------------
    >
    >char array[10] = "abcdefghij";
    >
    >for (int i = 0; i < 10; i++)
    >{
    > switch (array)
    > {
    > case 'a':
    > /* code */
    > break;
    > case 'b':
    > /* code */
    > break;
    > case 'c':
    > /* code */
    > break;
    >
    > default:
    > /* code */
    > break;
    > }


    // After the switch executes, control passes here.
    // You could retest and break here to get out of the for loop.
    // For example, breaking if case 'b'.

    if(array == 'b')
    break;

    >
    >}
    >
    >--------------------------------------------
    >
    >Is it possible to break out of the for loop from inside of one case-
    >statement, or do I have to use a workaround?


    I'm not aware of a double break command. A break statement stops
    execution of the smallest enclosing switch statement. I would break
    out of each as above. You might rethink the switch statement and
    recast it as a if-else series.

    Best wishes,

    Bob
    Bob, Feb 25, 2007
    #4
  5. Bill Pursell wrote:
    > On Feb 25, 11:16 am, Alexander Korsunsky <>
    > wrote:
    >
    >> char array[10] = "abcdefghij";

    >
    > It's unfortunate that this doesn't generate a
    > compiler warning in the same way that
    > int array[2] = { 1, 2, 3}; does.


    I agree. I will use array[] = "abcde"; in future.

    > There are at least 3 obvious ways:
    > 1) increment the index to cause your condition on the
    > for loop to terminate the loop (a workaround.)


    Doesn't seem to me, that this is good style... Correct me if I'm mistaken.

    > 2) goto


    I've heard that goto should not be used (anymore) because there are
    better ways.
    But in my situation it looks like that would be the best possibility,
    because I don't have to set up a variable and test it to be false, to
    continue the loop.

    > 3) fix the loop condition to more accurately reflect
    > whatever it is you are testing for. (Probably
    > the correct solution.)


    In my case, it isn't because I am checking a letter, and then executing
    different code for each different letter. This code calls functions
    which return error codes if they fail. To prevent the program to fail,
    the loop has to be stopped.

    Thanks for your help,
    Alexander Korsunsky
    Alexander Korsunsky, Feb 25, 2007
    #5
  6. Alexander Korsunsky

    Eric Sosman Guest

    Alexander Korsunsky wrote:
    > Hi!
    >
    > I have some code that looks similar to this:
    >
    > --------------------------------------------
    >
    > char array[10] = "abcdefghij";
    >
    > for (int i = 0; i < 10; i++)
    > {
    > switch (array)
    > {
    > case 'a':
    > /* code */
    > break;
    > case 'b':
    > /* code */
    > break;
    > case 'c':
    > /* code */
    > break;
    >
    > default:
    > /* code */
    > break;
    > }
    >
    > }
    >
    > --------------------------------------------
    >
    > Is it possible to break out of the for loop from inside of one case-
    > statement, or do I have to use a workaround?


    You cannot `break' from the inside of the `switch' to
    the outside of the `for'. Here is one alternative:

    for (int i = 0; i < 10; ++i) {
    switch(array) {
    case 'a':
    /* code */
    continue;
    case 'b':
    /* code */
    if (want_to_break_out)
    break;
    continue;
    default:
    /* code */
    continue;
    }
    break;
    }

    I cannot recommend this dodge for all circumstances.
    Code is read by compilers and by people; the former are the
    less important audience.

    --
    Eric Sosman
    lid
    Eric Sosman, Feb 25, 2007
    #6
  7. In article <>,
    Alexander Korsunsky <> wrote:
    ....
    >> There are at least 3 obvious ways:
    >> 1) increment the index to cause your condition on the
    >> for loop to terminate the loop (a workaround.)

    >
    >Doesn't seem to me, that this is good style... Correct me if I'm mistaken.


    The point is that the "short answer" to your question is "No, you can't
    do it (you have to do a workaround)". The slightly longer answer is
    "Yes, it is a mis-design in the language, but we have to live with it".
    The problem isn't so much the *lack* of "break 2" (as exists in shell),
    but rather the use of "break" in the syntax of "switch". "break" should
    be (i.e., have been) reserved for the looping constructs and "switch"
    clearly isn't a looping construct.

    I've asked this same question here in the past and have been told that
    "goto" is the best workaround (one of the few situations where "goto" is
    "permissible").
    Kenny McCormack, Feb 25, 2007
    #7
  8. Alexander Korsunsky

    Bob Guest

    On Sun, 25 Feb 2007 13:54:51 +0100, Alexander Korsunsky
    <> wrote:

    >Bill Pursell wrote:

    <snip>
    >> There are at least 3 obvious ways:
    >> 1) increment the index to cause your condition on the
    >> for loop to terminate the loop (a workaround.)

    >
    >Doesn't seem to me, that this is good style... Correct me if I'm mistaken.


    Sounds like a hard to maintain work around to me.

    >> 2) goto

    >
    >I've heard that goto should not be used (anymore) because there are
    >better ways.


    goto, continue, and break are all jump statements. IMHO, they all
    share some of the same issues although goto is the worst.

    >But in my situation it looks like that would be the best possibility,
    >because I don't have to set up a variable and test it to be false, to
    >continue the loop.
    >
    >> 3) fix the loop condition to more accurately reflect
    >> whatever it is you are testing for. (Probably
    >> the correct solution.)

    >
    >In my case, it isn't because I am checking a letter, and then executing
    >different code for each different letter. This code calls functions
    >which return error codes if they fail. To prevent the program to fail,
    >the loop has to be stopped.


    Then I would not use a switch statement at all. I'm not sure how many
    cases you are worrying about, but perhaps something like this:

    for (int i = 0; i < 10; i++)
    {
    if(function(array))
    break;
    }

    function returns an error code and may contain the switch as well, if
    needed.

    Best wishes,

    Bob
    Bob, Feb 25, 2007
    #8
  9. Alexander Korsunsky

    Flash Gordon Guest

    Bob wrote, On 25/02/07 13:21:
    > On Sun, 25 Feb 2007 13:54:51 +0100, Alexander Korsunsky
    > <> wrote:
    >
    >> Bill Pursell wrote:

    > <snip>
    >>> There are at least 3 obvious ways:
    >>> 1) increment the index to cause your condition on the
    >>> for loop to terminate the loop (a workaround.)

    >> Doesn't seem to me, that this is good style... Correct me if I'm mistaken.

    >
    > Sounds like a hard to maintain work around to me.


    Not something I would like.

    >>> 2) goto

    >> I've heard that goto should not be used (anymore) because there are
    >> better ways.

    >
    > goto, continue, and break are all jump statements. IMHO, they all
    > share some of the same issues although goto is the worst.


    setjmp/longjmp is worse IMHO. Which does not mean to say it isn't needed
    sometimes.

    >> But in my situation it looks like that would be the best possibility,
    >> because I don't have to set up a variable and test it to be false, to
    >> continue the loop.
    >>
    >>> 3) fix the loop condition to more accurately reflect
    >>> whatever it is you are testing for. (Probably
    >>> the correct solution.)

    >> In my case, it isn't because I am checking a letter, and then executing
    >> different code for each different letter. This code calls functions
    >> which return error codes if they fail. To prevent the program to fail,
    >> the loop has to be stopped.

    >
    > Then I would not use a switch statement at all. I'm not sure how many
    > cases you are worrying about, but perhaps something like this:
    >
    > for (int i = 0; i < 10; i++)
    > {
    > if(function(array))
    > break;
    > }
    >
    > function returns an error code and may contain the switch as well, if
    > needed.


    Or include the for in the function as well and use an early return in
    the switch.
    --
    Flash Gordon
    Flash Gordon, Feb 25, 2007
    #9
  10. Alexander Korsunsky

    Bill Pursell Guest

    On Feb 25, 12:54 pm, Alexander Korsunsky <>
    wrote:
    > Bill Pursell wrote:
    > > On Feb 25, 11:16 am, Alexander Korsunsky <>
    > > wrote:

    >
    >
    > > 3) fix the loop condition to more accurately reflect
    > > whatever it is you are testing for. (Probably
    > > the correct solution.)

    >
    > In my case, it isn't because I am checking a letter, and then executing
    > different code for each different letter. This code calls functions
    > which return error codes if they fail. To prevent the program to fail,
    > the loop has to be stopped.


    You might consider something like:
    for( ; !err_flag; ) {
    switch(value) {
    case 0:
    err_flag = do_something();
    break;
    ....

    --
    Bill Pursell
    Bill Pursell, Feb 25, 2007
    #10
  11. Alexander Korsunsky

    santosh Guest

    Alexander Korsunsky wrote:
    > Hi!
    >
    > I have some code that looks similar to this:
    >
    > char array[10] = "abcdefghij";
    >
    > for (int i = 0; i < 10; i++)
    > {
    > switch (array)
    > {
    > case 'a':
    > /* code */
    > break;
    > case 'b':
    > /* code */
    > break;
    > case 'c':
    > /* code */
    > break;
    >
    > default:
    > /* code */
    > break;
    > }
    >
    > }
    >
    >
    > Is it possible to break out of the for loop from inside of one case-
    > statement, or do I have to use a workaround?


    Essentially a workaround. C doesn't have multilevel breaks. You can do
    one of the following:

    1.
    int done = 0;
    for(i = 0; i < 10 || !done; i++) {
    switch {
    case 'a':
    /* do something */
    done = 1;
    break;
    /* ... */
    }
    }

    2.
    int done = 0;
    for(i = 0; i < 10; i++) {
    switch {
    case 'a':
    /* do something */
    done = 1;
    break;
    /* ... */
    }
    if(done) break;
    }

    3.
    for(i = 0; i < 10; i++) {
    switch {
    case 'a':
    /* do something */
    if(FINISHED) goto proceed;
    else break;
    /* ... */
    }
    }
    proceed:
    /* ... */
    santosh, Feb 25, 2007
    #11
  12. Alexander Korsunsky

    CBFalconer Guest

    Alexander Korsunsky wrote:
    >
    > I have some code that looks similar to this:
    >
    > --------------------------------------------
    > char array[10] = "abcdefghij";
    >
    > for (int i = 0; i < 10; i++)
    > {
    > switch (array)
    > {
    > case 'a':
    > /* code */

    goto label;

    > break;
    > case 'b':
    > /* code */
    > break;
    > default:
    > /* code */
    > break;
    > }
    > }

    label: /* some code */;
    > --------------------------------------------
    >
    > Is it possible to break out of the for loop from inside of one
    > case-statement, or do I have to use a workaround?


    Very easy. Just use a goto as illustrated above.

    --
    Chuck F (cbfalconer at maineline dot net)
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net>
    CBFalconer, Feb 25, 2007
    #12
  13. In article <>,
    vicky <> could have written:
    ....
    >apart it answer above. no need and solved have break with his from in
    >for of get by never is others problem it any break the two to enough
    >key is in problem their is and as result, ways programming, use the
    >explained say no words already you single co-ordination of


    Makes about as much sense like that as before, doesn't it?
    Kenny McCormack, Feb 25, 2007
    #13
  14. Alexander Korsunsky

    Default User Guest

    Bill Pursell wrote:

    > On Feb 25, 11:16 am, Alexander Korsunsky <>
    > wrote:
    >
    > >
    > > char array[10] = "abcdefghij";

    >
    > It's unfortunate that this doesn't generate a
    > compiler warning in the same way that
    > int array[2] = { 1, 2, 3}; does.


    I think the latter is a constraint violation. That's not true for the
    first, it's perfectly legal, although questionable and of course a
    warning could be issued if the compiler felt like it.



    Brian
    Default User, Feb 25, 2007
    #14
  15. "Bill Pursell" <> writes:
    [...]
    > There is no "break 3" type syntax in C, however.


    For which I'm extremely grateful.

    A multi-level break that requires you to specify the number of levels
    would lead to numerous hard-to-find bugs. Why force the programmer
    and the reader to *count* something? That's what computers are for.

    I'd like C to have a multi-level break construct, but the argument
    should refer to the *name* of the construct, perhaps a label. A
    number of other languages do this (Ada, Perl, et al).

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Feb 25, 2007
    #15
  16. CBFalconer <> writes:
    > Alexander Korsunsky wrote:
    >>
    >> I have some code that looks similar to this:
    >>
    >> --------------------------------------------
    >> char array[10] = "abcdefghij";
    >>
    >> for (int i = 0; i < 10; i++)
    >> {
    >> switch (array)
    >> {
    >> case 'a':
    >> /* code */

    > goto label;
    >
    >> break;
    >> case 'b':
    >> /* code */
    >> break;
    >> default:
    >> /* code */
    >> break;
    >> }
    >> }

    > label: /* some code */;
    >> --------------------------------------------
    >>
    >> Is it possible to break out of the for loop from inside of one
    >> case-statement, or do I have to use a workaround?

    >
    > Very easy. Just use a goto as illustrated above.


    Agreed. C should, IMHO, have a multi-level break construct. Given
    that it doesn't, a goto that does exactly the same thing that a
    multi-level break would have done is the best workaround. Distorting
    the code (e.g., by replacing a switch with an if/else chain) just to
    avoid the dreaded goto is a bad idea.

    I'd also use a more mnemonic name for the label. "label" is fine for
    an example, but not for real-world code. I might use something like
    "BREAK_OUTER_LOOP:".

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Feb 25, 2007
    #16
  17. "Default User" <> writes:
    > Bill Pursell wrote:
    >> On Feb 25, 11:16 am, Alexander Korsunsky <>
    >> wrote:
    >> > char array[10] = "abcdefghij";

    >>
    >> It's unfortunate that this doesn't generate a
    >> compiler warning in the same way that
    >> int array[2] = { 1, 2, 3}; does.

    >
    > I think the latter is a constraint violation. That's not true for the
    > first, it's perfectly legal, although questionable and of course a
    > warning could be issued if the compiler felt like it.


    For those not aware of the rule:

    char s[] = "abc";
    /* char s2[2] = "abc"; */
    char s3[3] = "abc";
    char s4[4] = "abc";
    char s5[5] = "abc";

    s is a 4-byte array containing { 'a', 'b', 'c', '\0' }.
    s2, I believe, is a constraint violation.
    s3 is a 3-byte array containing { 'a', 'b', 'c' }; it is *not* a string.
    s4, like s, is a 4-byte array containing { 'a', 'b', 'c', '\0' }.
    s5 is a 5-byte array containing { 'a', 'b', 'c', '\0', '\0' }.

    The only way (I think) for a string literal to specify a non-string
    (i.e., an array with no '\0' terminator) is to use it as the
    initializer for an array of exactly the right size. I suspect we'd be
    better off without this rule, which often leads to incorrect code
    where the programmer *meant* to create a valid string. Perhaps a
    special syntax to indicate that a string literal represents an array
    not terminated with a '\0' would have been useful.

    If you just want a string with no additional space, use the "[]" form
    and let the compiler figure out the required size. As I recently said
    here in another thread, counting is what computers are best at; let
    the compiler do it for you.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Feb 25, 2007
    #17
  18. Alexander Korsunsky

    matevzb Guest

    On Feb 25, 11:26 pm, Keith Thompson <> wrote:
    > "Default User" <> writes:
    > > Bill Pursell wrote:
    > >> On Feb 25, 11:16 am, Alexander Korsunsky <>
    > >> wrote:
    > >> > char array[10] = "abcdefghij";

    >
    > >> It's unfortunate that this doesn't generate a
    > >> compiler warning in the same way that
    > >> int array[2] = { 1, 2, 3}; does.

    >
    > > I think the latter is a constraint violation. That's not true for the
    > > first, it's perfectly legal, although questionable and of course a
    > > warning could be issued if the compiler felt like it.

    >
    > For those not aware of the rule:
    >
    > char s[] = "abc";
    > /* char s2[2] = "abc"; */
    > char s3[3] = "abc";
    > char s4[4] = "abc";
    > char s5[5] = "abc";
    >
    > s is a 4-byte array containing { 'a', 'b', 'c', '\0' }.
    > s2, I believe, is a constraint violation.
    > s3 is a 3-byte array containing { 'a', 'b', 'c' }; it is *not* a string.
    > s4, like s, is a 4-byte array containing { 'a', 'b', 'c', '\0' }.
    > s5 is a 5-byte array containing { 'a', 'b', 'c', '\0', '\0' }.

    And, to continue in this manner, it should probably be noted that e.g.
    s1024[1024] = "";
    should not be used for string initialization, as it will set all 1024
    characters to '\0'. Not usually noticed, but it may turn out to cause
    a major performance degradation.
    <snip>
    --
    WYCIWYG - what you C is what you get
    matevzb, Feb 25, 2007
    #18
  19. Alexander Korsunsky

    Default User Guest

    Keith Thompson wrote:

    > "Default User" <> writes:
    > > Bill Pursell wrote:
    > >> On Feb 25, 11:16 am, Alexander Korsunsky <>
    > >> wrote:
    > >> > char array[10] = "abcdefghij";
    > >>
    > >> It's unfortunate that this doesn't generate a
    > >> compiler warning in the same way that
    > >> int array[2] = { 1, 2, 3}; does.

    > >
    > > I think the latter is a constraint violation. That's not true for
    > > the first, it's perfectly legal, although questionable and of
    > > course a warning could be issued if the compiler felt like it.

    >
    > For those not aware of the rule:
    >
    > char s[] = "abc";
    > /* char s2[2] = "abc"; */
    > char s3[3] = "abc";
    > char s4[4] = "abc";
    > char s5[5] = "abc";
    >
    > s is a 4-byte array containing { 'a', 'b', 'c', '\0' }.
    > s2, I believe, is a constraint violation.


    That's my reading of the standard.

    > s3 is a 3-byte array containing { 'a', 'b', 'c' }; it is not a string.


    Right.

    > The only way (I think) for a string literal to specify a non-string
    > (i.e., an array with no '\0' terminator) is to use it as the
    > initializer for an array of exactly the right size. I suspect we'd be
    > better off without this rule, which often leads to incorrect code
    > where the programmer meant to create a valid string.


    C++ decided to remove that feature, so that's another of those subtle
    differences in the languages.




    Brian
    Default User, Feb 25, 2007
    #19
  20. On Feb 26, 10:26 am, "matevzb" <> wrote:
    > ...
    > And, to continue in this manner, it should probably be noted that
    > e.g.
    > s1024[1024] = "";
    > should not be used for string initialization, as it will set all
    > 1024 characters to '\0'. Not usually noticed, but it may turn out
    > to cause a major performance degradation.


    The golden rule is not to (micro-)optimise until there's a proven
    bottleneck.

    The real question is whether you actually need to initialise or
    not. I find it extremely rare that I actually need to initialise
    a character buffer to an empty string.

    Given the choice, most programmers will not initialise an object
    if they don't have to. [A notable exception is Richard Heathfield,
    though I believe he is more likely to use {0} than "".]

    --
    Peter
    Peter Nilsson, Feb 26, 2007
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Niv

    CASE statement & LOOP

    Niv, Jun 20, 2006, in forum: VHDL
    Replies:
    16
    Views:
    5,608
  2. Replies:
    16
    Views:
    3,585
    steve
    Jul 11, 2006
  3. break statement in a for loop

    , Apr 28, 2007, in forum: C Programming
    Replies:
    25
    Views:
    797
  4. Replies:
    12
    Views:
    957
  5. Isaac Won
    Replies:
    9
    Views:
    370
    Ulrich Eckhardt
    Mar 4, 2013
Loading...

Share This Page