acceptable use of goto?

R

Richard Heathfield

Bartc said:

A lot of work to eliminate the occasional goto as in the following
(uncompiled) code:

for (i=1; i<=N; +=i)

Presumably ++i ?
{
if (x==2) break;

switch (x)
{
case 2:
goto mylabel;
};

};
mylabel:

for(i = 1; i <= N && x != 2; ++i)
{
}

would do it.

<snip>
 
E

Ed Prochak

Bartc said:




Presumably ++i ?




for(i = 1; i <= N && x != 2; ++i)
{

}

would do it.

<snip>

AH, but that fails for the OP, since that requires completing a full
pass thru the loop. But it is useful to point out the feature of
multiple conditions. Just don't abuse it.
That seven page while loop I mentioned previously also had about 5
lines of conditions, about 25contitions all together! It really
should have been two separate programs.

Enjoy.
Ed
 
B

Bartc

Richard Heathfield said:
Bartc said:



Presumably ++i ?

Er, yes; I did say it was uncompiled.
for(i = 1; i <= N && x != 2; ++i)
{
}

would do it.

For that particular fragment, yes. But in practice I may want to exit in the
middle of the loop.

It just seems wrong that break can be used in a for-loop body, by itself or
in an if statement, but not in a switch statement or a nested for- or
while-loop.

The following is an extract from a piece of code I posted last week. The
goto was left in inadvertently. I wanted to exit the outer while loop from
inside the switch statement.

This example is easy to fix, but the point is I was momentarily thrown
because I couldn't use break there (eg. break 2) -- I had to stop and think
of a workaround. The goto was an instant fix. But I should not have to fight
the language.

while(1)
{...
switch (c)
{
......
default:
goto xyzzy;
};
};
xyzzy:
 
R

Richard Heathfield

Bartc said:

[...] But in practice I may want to exit in
the middle of the loop.

Understood. At least, kind of understood. I know that such a desire is
relatively commonplace, but it isn't something I have ever felt an urge to
do in C. Bizarrely, it *is* something I felt an urge to do in BASIC, and
goto was the way I solved that problem. But at the same time that I was
learning C, I was solidly won over to the idea of one-entry-one-exit for
every control structure (functions, loops, switches, and ifs). So at the
very moment that I finally got my hands on a language that supported
unstructured loops (via break), I stopped wanting to use them!
It just seems wrong that break can be used in a for-loop body, by itself
or in an if statement, but not in a switch statement or a nested for- or
while-loop.

Yes, break shouldn't be overloaded like that. In fact, break shouldn't be
needed in a switch at all! Rather, there should be a keyword such as
'fallthrough' (okay, maybe there are better names for it), leaving break
purely for breaking out of loops (for those who insist on doing such
things).
The following is an extract from a piece of code I posted last week. The
goto was left in inadvertently. I wanted to exit the outer while loop
from inside the switch statement.

I'd like to say I sympathise, but it's the wrong word here, because I never
want to do that, so sym- doesn't really work. But I can understand your
frustration with the lack of a language feature to fulfil an apparently
simple and obvious desire (my own pet annoyance is the absence of
#ifntypedef!).
This example is easy to fix, but the point is I was momentarily thrown
because I couldn't use break there (eg. break 2) -- I had to stop and
think of a workaround. The goto was an instant fix. But I should not have
to fight the language.

I don't have to, because I automatically structure my code in such a way
that it is never necessary. On the other hand, my coding style is not one
that seems particularly popular around here! :)
 
B

Ben Bacarisse

Richard Heathfield said:
(my own pet annoyance is the absence of
#ifntypedef!).

They say it is not a new C standard unless static is given a new
meaning, so I think you should propose:

static typedef long number;

to do the typedef only if number is not already a type synonym. It
would do part of what you want.
 
B

Bartc

Richard Heathfield said:
Bartc said:
...leaving break purely for breaking out of loops (for those who insist
on doing such things).

I could go on at length about why break (and extensions of it) is desirable
and makes code easier to read. But I won't. Just trust me.
... But I can understand your
frustration with the lack of a language feature to fulfil an apparently
simple and obvious desire (my own pet annoyance is the absence of
#ifntypedef!).

I don't think #ifntypedef is so simple and obvious. I could live without it!

And I think it may not be practical, because these # ops I understand are
processed before any analysis of the underlying C source so will not know
anything about existing typedefs.
 
R

Richard Heathfield

Bartc said:
I could go on at length about why break (and extensions of it) is
desirable and makes code easier to read. But I won't. Just trust me.

And I could go on at length about why it isn't and doesn't. But I will
extend to you the same courtesy that you extended to me. :)
I don't think #ifntypedef is so simple and obvious. I could live without
it!

Well, I have to live without it, obviously.
And I think it may not be practical, because these # ops I understand are
processed before any analysis of the underlying C source so will not know
anything about existing typedefs.

Right. I understand why I can't have it, but that doesn't stop me wanting
it. The "static" suggestion elsethread is intriguing!
 
J

João Jerónimo

Richard said:
[...] But in practice I may want to exit in
the middle of the loop.

Understood. At least, kind of understood. I know that such a desire is
relatively commonplace, but it isn't something I have ever felt an urge to
do in C. Bizarrely, it *is* something I felt an urge to do in BASIC, and
goto was the way I solved that problem. But at the same time that I was
learning C, I was solidly won over to the idea of one-entry-one-exit for
every control structure (functions, loops, switches, and ifs). So at the
very moment that I finally got my hands on a language that supported
unstructured loops (via break), I stopped wanting to use them!

If I declare an integer array with:
int myarray[] = {5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0};
And want to write a routine to print it like this:
(5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0)
, my best hint would be (untested):

--------------------------------------------------
void print_int_array( int *array, int arraylen )
{
assert( arraylen >= 1 );

int *arrayend = array+arraylen;

printf("(");
for(;;) {
printf("%d", *array);
array++;
if ( array == arrayend )
break;
printf(", ");
}
printf(")");
}
--------------------------------------------------

Now, please point me out a better solution.
(This is not strictly the case of a loop with multiple exits, but helps to
ilustrate the idea...)

JJ
 
R

Richard Heathfield

João Jerónimo said:

If I declare an integer array with:
int myarray[] = {5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0};
And want to write a routine to print it like this:
(5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0)
, my best hint would be (untested):

--------------------------------------------------
void print_int_array( int *array, int arraylen )
{
assert( arraylen >= 1 );

int *arrayend = array+arraylen;

printf("(");
for(;;) {
printf("%d", *array);
array++;
if ( array == arrayend )
break;
printf(", ");
}
printf(")");
}

void print_int_array(int *array, size_t arraylen)
{
assert(arraylen >= 1);
printf("(%d", *array++);
while(--arraylen)
{
printf(", %d", *array++);
}
printf(")");
}

I accept that my solution duplicates the %d line, but the payoff is that,
overall, the code is shorter and simpler.
 
M

Morris Dovey

Richard said:
João Jerónimo said:

If I declare an integer array with:
int myarray[] = {5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0};
And want to write a routine to print it like this:
(5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0)
, my best hint would be (untested):

--------------------------------------------------
void print_int_array( int *array, int arraylen )
{
assert( arraylen >= 1 );

int *arrayend = array+arraylen;

printf("(");
for(;;) {
printf("%d", *array);
array++;
if ( array == arrayend )
break;
printf(", ");
}
printf(")");
}

void print_int_array(int *array, size_t arraylen)
{
assert(arraylen >= 1);
printf("(%d", *array++);
while(--arraylen)
{
printf(", %d", *array++);
}
printf(")");
}

void print_int_array(int *array, int arraylen)
{ assert(arraylen >= 1);
do printf(" %d",*array++);
while (--arraylen);
}

Is there a prize?
 
W

Willem

Richard wrote:
) void print_int_array(int *array, size_t arraylen)
) {
) assert(arraylen >= 1);
) printf("(%d", *array++);
) while(--arraylen)
) {
) printf(", %d", *array++);
) }
) printf(")");
) }
)
) I accept that my solution duplicates the %d line, but the payoff is that,
) overall, the code is shorter and simpler.

Avoiding the double %d at the cost of increased obfuscation:

void print_int_array(int *array, size_t arraylen)
{
assert(arraylen >= 1);
char *sep = "(";
while(--arraylen)
{
printf("%s%d", sep, *array++);
sep = ", ";
}
printf(")");
}

Of course, the idiom:
if (arraylen > 1) printf(", ");
works too, is closest to the OP's C while avoiding the break.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
B

Ben Bacarisse

João Jerónimo said:
If I declare an integer array with:
int myarray[] = {5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0};
And want to write a routine to print it like this:
(5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0)

I do it like this:

void print_int_array(int *array, size_t arraylen)
{
putchar('(');
for (size_t i = 0; i < arraylen; i++)
printf("%s%d", (i ? ", " : ""), array);
putchar(')');
}
 
M

Morris Dovey

Ben said:
João Jerónimo said:
If I declare an integer array with:
int myarray[] = {5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0};
And want to write a routine to print it like this:
(5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0)

I do it like this:

void print_int_array(int *array, size_t arraylen)
{
putchar('(');
for (size_t i = 0; i < arraylen; i++)
printf("%s%d", (i ? ", " : ""), array);
putchar(')');
}


I like your use of '?:'. My poor old compiler choked on defining
i inside the for statement, so I tried:

#include <stdio.h>

void print_int_array(int *array, size_t arraylen)
{ putchar('(');
do printf("%d%s",*array++,--arraylen?", ":")\n");
while (arraylen);
}

int main(void)
{ int x[] = {5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0};
print_int_array(x,12);
return 0;
}
 
B

Ben Bacarisse

Morris Dovey said:
Ben said:
João Jerónimo said:
If I declare an integer array with:
int myarray[] = {5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0};
And want to write a routine to print it like this:
(5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0)

I do it like this:

void print_int_array(int *array, size_t arraylen)
{
putchar('(');
for (size_t i = 0; i < arraylen; i++)
printf("%s%d", (i ? ", " : ""), array);
putchar(')');
}


I like your use of '?:'. My poor old compiler choked on defining
i inside the for statement, so I tried:


The best solution is just to define 'size_t i;' at the top. I
realised I'd been unhelpfully 99ish after I hit send.
#include <stdio.h>

void print_int_array(int *array, size_t arraylen)
{ putchar('(');
do printf("%d%s",*array++,--arraylen?", ":")\n");
while (arraylen);
}

Not to my taste, I have to say, but each to his or her own. I don't
like adding an extra special case (no elements) unless I am forced to
(you do know what your code does when there are no elements?). I'd
not just deal with no elements gracefully. Also, I find the loss of
symmetry disappointing -- it is hard to see that the list really is
bracketed.

Oh, and shake some spaces into it!!
 
M

Morris Dovey

Ben said:
Morris Dovey said:
Ben Bacarisse wrote:
I do it like this:

void print_int_array(int *array, size_t arraylen)
{
putchar('(');
for (size_t i = 0; i < arraylen; i++)
printf("%s%d", (i ? ", " : ""), array);
putchar(')');
}


I like your use of '?:'. My poor old compiler choked on defining
i inside the for statement, so I tried:


The best solution is just to define 'size_t i;' at the top. I
realised I'd been unhelpfully 99ish after I hit send.
#include <stdio.h>

void print_int_array(int *array, size_t arraylen)
{ putchar('(');
do printf("%d%s",*array++,--arraylen?", ":")\n");
while (arraylen);
}

Not to my taste, I have to say, but each to his or her own. I don't
like adding an extra special case (no elements) unless I am forced to
(you do know what your code does when there are no elements?).


If you have no elements, why would you print them? :p
I'd
not just deal with no elements gracefully. Also, I find the loss of
symmetry disappointing -- it is hard to see that the list really is
bracketed.

It is? [ said:
Oh, and shake some spaces into it!!

Sheesh - there's an /extra/ space in there already! Next, I
suppose you'll be wanting extra braces, as well.
 
R

Richard

Morris Dovey said:
Ben said:
João Jerónimo said:
If I declare an integer array with:
int myarray[] = {5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0};
And want to write a routine to print it like this:
(5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0)

I do it like this:

void print_int_array(int *array, size_t arraylen)
{
putchar('(');
for (size_t i = 0; i < arraylen; i++)
printf("%s%d", (i ? ", " : ""), array);
putchar(')');
}


I like your use of '?:'. My poor old compiler choked on defining
i inside the for statement, so I tried:


What's to like about using "?" here? It seems quite an obvious and
standard thing to do.
#include <stdio.h>

void print_int_array(int *array, size_t arraylen)
{ putchar('(');
do printf("%d%s",*array++,--arraylen?", ":")\n");
while (arraylen);
}

Horrible since it doesn't detect the arraylen being zero. At least the
previous would only print empty brackets in this case. The print is
far more complicated than it need be and, IMO, the original suggestion
is much cleaner and easier to read.
int main(void)
{ int x[] = {5, 6, 3, 4, 8, 7, 2, 3, 4, 5, 6, 0};
print_int_array(x,12);
return 0;
}
 
R

Richard

Morris Dovey said:
Ben said:
Morris Dovey said:
Ben Bacarisse wrote:
I do it like this:

void print_int_array(int *array, size_t arraylen)
{
putchar('(');
for (size_t i = 0; i < arraylen; i++)
printf("%s%d", (i ? ", " : ""), array);
putchar(')');
}

I like your use of '?:'. My poor old compiler choked on defining
i inside the for statement, so I tried:


The best solution is just to define 'size_t i;' at the top. I
realised I'd been unhelpfully 99ish after I hit send.
#include <stdio.h>

void print_int_array(int *array, size_t arraylen)
{ putchar('(');
do printf("%d%s",*array++,--arraylen?", ":")\n");
while (arraylen);
}

Not to my taste, I have to say, but each to his or her own. I don't
like adding an extra special case (no elements) unless I am forced to
(you do know what your code does when there are no elements?).


If you have no elements, why would you print them? :p


You wouldn't. You especially would not want to print possibly thousands
of corrupt data elements as your code would. Always doe the zero check
in the called function. It should not be the job of the calling code
especially when there is zero overhead by doing it properly as in Ben's
example.
 
M

Morris Dovey

Richard said:
You wouldn't. You especially would not want to print possibly thousands
of corrupt data elements as your code would. Always doe the zero check
in the called function. It should not be the job of the calling code
especially when there is zero overhead by doing it properly as in Ben's
example.

A simple matter of programming philosophy. Mine is to minimize
resource (memory and CPU) consumption as early as possible,
rather than to thrash needlessly.

Others prefer to structure their code so that it goes through all
the motions even when there's no work to be done. More power to
'em, I guess.
 
R

Richard

Morris Dovey said:
A simple matter of programming philosophy. Mine is to minimize

Yes. Doing is safely or doing it not so safely and applying unnecessary
rules that must be obeyed by the routines which call your function. I
know which one I prefer.
resource (memory and CPU) consumption as early as possible,
rather than to thrash needlessly.

What are you talking about? What thrash? Here is Bens code again:

,----
| >> >> void print_int_array(int *array, size_t arraylen)
| >> >> {
| >> >> putchar('(');
| >> >> for (size_t i = 0; i < arraylen; i++)
| >> >> printf("%s%d", (i ? ", " : ""), array);
| >> >> putchar(')');
| >> >> }
`----

This is no slower than yours. It also removes the need to check for 0 by
the caller.
Others prefer to structure their code so that it goes through all
the motions even when there's no work to be done. More power to
'em, I guess.

You didn't save anything with this approach - you only left the
possibility for a caller to crash the system by calling it with a zero
option.

Even if you had done an explicit zero check (or needed to) then the
overhead was nothing compared to the display loop.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top