Why?
I know that the code would always be executed on the head of the list the first time through, if that’s what you mean. We are trying to restart the loop, so that the code is run on each node again. Consider the possibility that the code after the test is dependent on the code before it, or that the head of the list changes.
So presumably what you want is this:
for element = headOfList to end
block A
if condition then element = headOfList
block B
next element
In that case, the loop starts with element at the head. block A is executed for each element, and on each iteration of the loop, it checks the condition and sets element to the head as appropriate. Then block B is executed on whatever element is.
Straight up, the use of goto is the least problematic element of this code. First, this code is not suitable for use unless you’ve actually proved that it always terminates or can handle an infinite loop. Secondly, this code is subtle, and would be very difficult to understand as a maintenance programmer. That’s the guy you’re writing for; not you. If the head of the list can change, then this is pretty much impossible to maintain.
In all honesty, if you write code like this, you’re a liability to whatever team you’re on and really shouldn’t be permitted near a keyboard. I’d have to see a realistic example to suggest the right way to handle a situation like this, but I can say with complete certainty that this ain’t it.
The anti-goto bandwagon seems to consist of a lot of reflexive knee jerking based on a single seminal (and quite well written) paper by Dijkstra called “Goto considered harmful”. While it is true that excessive and indiscriminite use of goto is indeed harmful, so are a lot of other coding constructs that can be abused. Automatic goto-avoidance, to me, often seems to lead to far more tortured code than is neccesary.
break, continue and next are just semantically prettier forms of goto that are far more limiting in their use. Trying to reformulate goto into a convoluted permutation of the above is worse than useless because it leads to even more horribly unreadable code. In particular, break et al don’t allow you to jump out of more than 1 layer of a loop which is often neccesary. Theres no logical reason for saying that break is any better than goto when used in this context.
No. I just told you that is exactly not what I want. Perhaps you might climb down from your pedestal and listen to me for a moment?
For each element in the list, certain code is run. After (or in the middle of) that code, it’s possible a circumstance might exist in which the entire loop needs to be restarted. That is, for every element, the entire piece of code is run again. And so we use a goto, or a break combined with a do-while, to accomplish that.
I only presented this as a hypothetical, which I admitted was unlikely, to make my point. If you consider it completely unrealistic, fine – that’s a strike against my argument. I don’t need to be told whether I should be “permitted near a keyboard.”
That’s not the impression I got from that thread. It seemed to me the general concensus was to avoid them, but occasional use is acceptable, and demonizing GOTO was useful back in the day but is now mostly irrational.
If you “must” use goto, then your code is not designed properly.
To briefly address the OP before going to bed:
case 1 - If you want to short-circuit a loop, just use a do-while/repeat-until instead of a for-next.
case 2 - Exceptions, baby. Throw the damn thing, that’s what it’s for.
case 3 - Again, replace the for-next with a do-while or repeat-until, and you can restart the list any time you want without a goto.
Count me as another crotchety coder who thinks gotos are the signs of an amateur (either that, or you’re programming in BASIC ).
Consider the example:
restart:
for (elem = start_of_list; elem != end_of_list; elem++)
{
elem = (elem * 2) % 3 + 1;
if (elem == 0)
goto restart;
elem *= 2;
}
In this case, it keeps traversing through the list until all the elements fulfil the condition (elem * 2) % 3 + 1 == 0. Simply setting the elem to head will not work in this case.
I wrote a goto just yesterday - in COBOL.
Say what? If that were true, then using goto would completely break your program. You’d likely return to an invalid address at the end of your function.
What a strange and convoluted example. What list? Without type specifications I am assuming all the variables are integers, but that doesn’t seem quite right. It seems like you are going to a damn lot of trouble to set the integer “elem” to a particular value. Please tell me what you are trying to accomplish, or update the example.
Okay, it doesn’t make sense.
Remind me to never answer programming questions before noon. (Fortunately, work doesn’t start until 2pm.)
It’s always possible to dream up some code that looks like it could benefit from a goto. And the answer to that problem is, “don’t write code that looks like it could benefit from a goto”.
If you find yourself thinking a goto is the only way out of the box you’ve programmed yourself into, time to step back and think a little harder about the problem and how to solve it.
Well, of course it’s a convoluted example, it was meant to demonstrate a possible situation where goto is likely, not a likely one. Okay, heres an example off the top of my head, say you were crazy enough to implement your own encryption system that implements a “digital key lock”. Like a normal lock, you have to insert a “key” that turns all the barrels to the right place at once. Furthermore, you need it to only unlock after a specified number of tries. You might try and implement it something like this:
bool digital_lock(int key[32])
{
const int[] lock = {12, 34, 56, 81, 99, 12...}; //change these for every program
const int max_num_tries = 17; //change these for every program
int num_tries = 0;
repeat:
for (int i = 0; i < 32; i++)
{
lock* = (lock* + key*) % 100;
if (lock* != 0)
goto repeat;
num_tries++;
}
return (num_tries == max_num_tries);
}
The advantage of this code is that if the hacker enters the wrong key, then the program will be stuck in an infinite loop but the right key might take a few minutes to generate so theres no way of telling if your on the right track or not. Obviously, it’s an incredibly bad encryption system, but at least it’s a practical example.
Quite. I have used goto twice in ten years so it’s not like I make a habit of it. I think multiple return points are a greater evil. Goto is actually recommended for error handling for the Oracle Pro*C programs (SQL embedded in C) I often deal with. An error can occur in a block of SQL code which doesn’t directly interact with the surrounding C code. You can use a whenever directive to send the program to a goto label if the SQL fails.
I get jumped on whenever I post my code so this is from an Oracle programming guide. Blame Larry.
EXEC SQL WHEN NOT FOUND GOTO no_more;
for(;;)
{
EXEC SQL FETCH emp_cursor INTO :emp_name, :emp_sal;
// do fun stuff with salaries
}
no_more: