Sign in to follow this  
ManaStone

How do I do this without using goto statements?

Recommended Posts

ManaStone    148
Right now I am working on a program that generates pseudo code from an activity diagram. I am working out some diagram scenarios and trying to put it into code to help me come up with a plan to code the translation. There is one that I can’t figure out how to do without using a goto statement and I know that as a rule of thumb C++ programmers are not supposed to use those. This is the code that best describes the graph
	while(func1()==true)
	{
		func2();
		while(func3()==true)
		{
			func4();
			if(func5()==true)
			{
				goto g1;
			}
			
		}
		func6();
	}
g1:
	func7();


Also, if I were to copy everything after the outer while loop into the if statement and then return like in the code below, it would be way too impractical.
	while(func1()==true)
	{
		func2();
		while(func3()==true)
		{
			func4();
			if(func5()==true)
			{
				func7()
				return;
			}
			
		}
		func6();
	}

	func7();



Anyone know how I can do this? Is there a way I can use a double break or something? [Edited by - ManaStone on August 18, 2008 3:14:23 AM]

Share this post


Link to post
Share on other sites
_Madman_    100
Sometimes goto is not the ultimate evil. It's ultimate evil to some guys who spend all of their lives to write a book on how to write clean code.

In industry goto sometimes is way better than ugly hacks that are invented just to avoid it.

It's just like OOP, when it's too much, it's PITA.

Share this post


Link to post
Share on other sites
hh10k    589
Just use a flag


bool finished = false
while (!finished && func1())
{
func2();
while(!finished && func3())
{
func4();
finished = func5();
}
if (!finished)
{
func6();
}
}
func7();



It looks like more typing, but a properly named flag that describes the loop will help readability. I have faith that any decent compiler will optimise it to the same thing as well.

Share this post


Link to post
Share on other sites
Rattenhirn    3114
You could use a flag:


bool done = false
while(!done && func1()==true)
{
func2();
while(!done && func3()==true)
{
func4();
if(func5()==true)
{
done = true;
}

}
if (!done)
func6();
}
func7();



It's likeley that there's a more elegant solution, depending on what funcs 1-6 actually do.

Share this post


Link to post
Share on other sites
ManaStone    148
Thanks for the advice. I'll probably end up using the goto though. Generating all the additional code for flags looks like it would be more tedious than it needs to be. I really wish C++ had the ultimate break that would get out of every loop. Perhaps I'll just have the pseudo code say Complete Break and then the programmer writes the code he can just add in the flags.

Share this post


Link to post
Share on other sites
DaBono    1496
Just use the goto. Yes, you could use some signal flag, but that would just make the code less intuitive. Give the label some descriptive name, add a comment what is done and it's quite comprehensible what happens.

The reason most programmers detest goto is that it can be used to make incomprehensible code. Using goto to break out of nested loops is fine. Using goto for any other flow control is frowned upon, especially if one jumps backwards in the program.

Share this post


Link to post
Share on other sites
OrangyTang    1298
Is the goto in your generated code, or your actual code? Gotos tend to be much more common (and more tolerated) in generated code since (in theory) no one ever has to maintain it directly, and can simplify the generating code.

Share this post


Link to post
Share on other sites
mceier    150
You could create another function, that will hold inner loop:


func8:
while(func3()==true)
{
func4();
if(func5()==true)
{
return true;
}
}
return false;

main:
while(func1()==true)
{
func2();
if (func8()) break;
func6();
}
func7();


Share this post


Link to post
Share on other sites
ToohrVyk    1596
mceier does have an element of the solution. If your two inner loops somehow form a compact set of functionality that can be jumped out of, then that set of functionality should be given a name and placed in its own method. The actual details of how this should be happening obviously depend on the exact algorithm being used. Therefore:

void factored_method()
{
while(func1())
{
func2();
while(func3())
{
func4();
if(func5()) return;
}
func6();
}
}

void original_method()
{
factored_method();
func7();
}

Share this post


Link to post
Share on other sites
losethos    100
Wow! A double break! That's a cool idea! I wrote my own compiler that's roughly C/C++. I might add that. It's funny -- I learned there was a "continue" statement in C/C++. I had never used it or seen it. I added it, just kinda guessing what it might do. (Too lazy to check a standard compiler.)

Share this post


Link to post
Share on other sites
ToohrVyk    1596
Losethos: from my language design experience, adding features to a language because they are "cool" is an excellent way to get an overly bloated and badly fitting language. Always consider the many alternatives that have already been invented by other language designers before rolling out your own. A good example would be Java's labeled break statements, which are by far superior to anything "double break" may mean.

Share this post


Link to post
Share on other sites
Daaark    3553
Quote:
Original post by ManaStone
I really wish C++ had the ultimate break that would get out of every loop.
That's exactly what your goto statement did. It jumps out of your loop to another address, just like a break would do.

What's the big deal? You must have read too deep into someone's anti-goto sentiments. That rule gets hammered into people way too much. People learn how to properly write functions and classes these days, we aren't 6 months out from people writing oldschool 'goto linenumber' BASIC code.

The only bad thing that can happen is that you create spaghetti code that is impossible to follow. You haven't done that here. It's a perfectly valid flow control statement.

Share this post


Link to post
Share on other sites
losethos    100
ToohrVyk,

On second thought, I removed the double_break. Thanks for talking me out of it. Goto is fine and actually clearer since the label catches your eye -- no need to bloat the language.

Share this post


Link to post
Share on other sites
losethos    100
The double_break added a bunch of parameters to internal compiler routines, slowing it down... Thanks to you, I was inspired to remove the "continue" statement too! I don't use that crappy thing. If I were a teacher, "goto" would be fine in very limited circumstances but that "continue" statement would be banned because no real-world programmers use it! Let's take a poll... anybody use the C/C++ "continue" statement? Screw that--keep my compiler lean.



Share this post


Link to post
Share on other sites
ToohrVyk    1596
Quote:
Original post by losethos
Let's take a poll... anybody use the C/C++ "continue" statement? Screw that--keep my compiler lean.


I do, more than break actually (you can break out of a loop by correct use of the loop condition, but selectively dropping out of a loop iteration before it's over is harder).

As far as 'continue' goes, it should be fairly easy to implement on most code generation architectures with at most a single additional parameter: it is usually implemented as a "goto end;" with a fresh "end:" label being added automatically at the end of the loop body. It can even be done at parsing time!

Share this post


Link to post
Share on other sites
dave    2187
I do occasionally, why not? I tend to take opinions lightly when someone says DONT EVER DO X, simply because it is situation dependant.

Share this post


Link to post
Share on other sites
Antheus    2409
This doesn't really give enough context to find a solution. One, perfectly valid solution is this:
try {
while(condition1())
{
func1();
while(condition2())
{
func2();
if(condition3()) throw std::exception("Some error");
}
func3();
}
} catch (std::exception &e) {
}
func4();


If condition3 represents an error, then exceptions are what can be used.

The core of the problem here lies simply in that individual functions do not encapsulate functionality well, since they need to manipulate caller's context.

But all of this is mostly pointless. *Which activity?* Tweaking a solution doesn't bring many benefits if the solution itself is unsuitable.

Share this post


Link to post
Share on other sites
Spoonbender    1258
Quote:
Original post by Daaark
That's exactly what your goto statement did. It jumps out of your loop to another address, just like a break would do.

What's the big deal? You must have read too deep into someone's anti-goto sentiments. That rule gets hammered into people way too much. People learn how to properly write functions and classes these days, we aren't 6 months out from people writing oldschool 'goto linenumber' BASIC code.

Um, sure you could use a goto. But *why*? Why not do the proper solution and put the loops in their own function, from which you can return. No need for goto, no need for multiple breaks. Just return when you want to exit the loops.

Nested loops are the most common justification for gotos I see. And it's still wrong. That's what functions are for. You should get used to those. They're there for a reason.

And this is exactly why use of goto is generally discouraged. Because it creates programmers whose solution to everything is "one long function, and use goto instead of factoring out into smaller functions".

I agree, the use of goto in this case isn't overly hard to follow, but it's still pointless, because you can achieve the same without using goto.

And the problem is that even if your use of goto is harmless, the programmer reading the code doesn't know that. He still has to read through the code verifying which gotos jump to which labels, and vice versa, to even figure out whether or not it's spaghetti code.

If you need to be able to jump out of a block of code, then that block should be a separate function.
If you need to be able to jump *to* a block of code, then it should most likely also be a separate function.

I know that almost every C/C++ programmer starts out cramming everything into the main() function. And then they start writing one or two other functions, and still cramming everything into those.
And then they do like you, saying "Oh, but my code doesn't fit, I'd better use some gotos", when they should just accept that they're going to have more than 3 functions in their program.

Share this post


Link to post
Share on other sites
Sneftel    1788
[quote]Original post by Spoonbender
Quote:
Original post by Daaark
That's exactly what your goto statement did. It jumps out of your loop to another address, Um, sure you could use a goto. But *why*? Why not do the proper solution and put the loops in their own function, from which you can return. No need for goto, no need for multiple breaks. Just return when you want to exit the loops.
Because some nested loops don't want to be separate functions. Choosing function granularity to avoid ever having to use goto is screwed-up priorities.

Share this post


Link to post
Share on other sites
_Madman_    100
Quote:
Original post by Spoonbender
Quote:
Original post by Daaark
That's exactly what your goto statement did. It jumps out of your loop to another address, just like a break would do.

What's the big deal? You must have read too deep into someone's anti-goto sentiments. That rule gets hammered into people way too much. People learn how to properly write functions and classes these days, we aren't 6 months out from people writing oldschool 'goto linenumber' BASIC code.

Um, sure you could use a goto. But *why*? Why not do the proper solution and put the loops in their own function, from which you can return. No need for goto, no need for multiple breaks. Just return when you want to exit the loops.

Nested loops are the most common justification for gotos I see. And it's still wrong. That's what functions are for. You should get used to those. They're there for a reason.

And this is exactly why use of goto is generally discouraged. Because it creates programmers whose solution to everything is "one long function, and use goto instead of factoring out into smaller functions".

I agree, the use of goto in this case isn't overly hard to follow, but it's still pointless, because you can achieve the same without using goto.

And the problem is that even if your use of goto is harmless, the programmer reading the code doesn't know that. He still has to read through the code verifying which gotos jump to which labels, and vice versa, to even figure out whether or not it's spaghetti code.

If you need to be able to jump out of a block of code, then that block should be a separate function.
If you need to be able to jump *to* a block of code, then it should most likely also be a separate function.

I know that almost every C/C++ programmer starts out cramming everything into the main() function. And then they start writing one or two other functions, and still cramming everything into those.
And then they do like you, saying "Oh, but my code doesn't fit, I'd better use some gotos", when they should just accept that they're going to have more than 3 functions in their program.


That's what C/C++ function call overhead is all about...

In order to stay away from perfectly valid and harmless goto you just add a whole lot of register pushing and popping on the stack in inner loop. (Inline f/n's and optimizations might or might not work here, they are suggestions after all)

Don't invent some frighteningly insane constructs just to avoid goto, if it's clear and valid, use it. If someone have a problem with understanding the original code, he shouldn't be a coder in the first place.

Share this post


Link to post
Share on other sites
Daaark    3553
Quote:
Original post by Spoonbender
And the problem is that even if your use of goto is harmless, the programmer reading the code doesn't know that. He still has to read through the code verifying which gotos jump to which labels, and vice versa, to even figure out whether or not it's spaghetti code.
I disagree with everything you wrote here.

His goto is not hard to follow. It's like a 3 line jump, and it's plain as day. Spoon, you're like a lot of people here who love to over engineer solutions to simple problems. You talk about hard to follow things, and then you suggest a completely un-needed, more complex work around to solve a problem that doesn't even exist!

goto is no different than any other keyword in the C derived languages, and can be used well, or abused and used very poorly. This case is not one of the later. This use is exactly what it's for.

Share this post


Link to post
Share on other sites
Telastyn    3777
IMO

Give me an exception or flag or inner function any day. Goto/break/continue harm readability and the ability to maintain the code. Maintenance is hard enough without convoluting common flow control.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this