|
No!
It's not a hard and fast rule - it depends on the complexity of what you are doing and why you might need it.
Sorry - but it's an experience thing, not something you can easily take down to a list of "if this and this and this, but not that or that, then..."
It's like driving a car - after a while you get a feel for "Is now a good time to pull out of this side turning?". It's not something you can easily explain.
Ideological Purity is no substitute for being able to stick your thumb down a pipe to stop the water
|
|
|
|
|
Not that I have used it, but the case some have made is breaking out of deeply nested loops (and not with exceptions):
for (i = 0; i < end; i++) {
doSomething();
for(j = obj[i].getAnotherObj(); j++; obj[i].end()) {
doSomethingElse();
for(k = anotherObj[j].getYetAnotherObj(); k++; anotherObj[j].end()) {
if (yetAnotherObj[k].condition())
goto breakOutOfDeeplyNestedLoop;
doYetSomethingElse();
}
blahBlah();
}
blahBlahBlah();
}
breakOutOfDeeplyNestedLoop:
moreStuffInThisMethod();
You could use exceptions, but that's really a misuse of them if the condition is not truly exceptional.
|
|
|
|
|
Ah yes, in some of my console apps I have a while loop for the console input, with continue to indicate that the command was recognised and bypass the rest of the commands in the loop.
Of course once I nested a for loop, I had to use a bool to ensure whether the loop should have used continue or not.
So assuming a similar scenario, instead of
while(settext())
{
if(!stricmp(text, "something"))
{
DoStuff();
continue; }
if(!strincmp(text, sizeof("other thing ")-1, "other thing "))
{
for(unsigned int i = 0; i < StringArray.size(); ++i)
{
if(!stricmp(text+sizeof("other thing ")-1, StringArray[i]))
{
StringArray.erase(i);
break; }
}
ReportError("parameter not found");
continue; }
if(!stricmp(text, "asparagus"))
{
continue; }
ReportError("command not found);
JumpHere:
continue; // Labels must have a statement
}
So that would be an applicable scenario?
modified 28-Feb-12 14:49pm.
|
|
|
|
|
Good example exactly of not using goto at all,
it's easily converted to an if then else situation.
which increases readability if u would ask me.
while(settext())
{
if(!stricmp(text, "something"))
{
DoStuff();
}
else if(!strincmp(text, sizeof("other thing ")-1, "other thing "))
{
for(unsigned int i = 0; i < StringArray.size(); ++i)
{
if(!stricmp(text+sizeof("other thing ")-1, StringArray[i]))
{
StringArray.erase(i);
break;
}
}
ReportError("parameter not found");
}
else if(!stricmp(text, "asparagus"))
{
}
else
{
ReportError("command not found");
}
}
|
|
|
|
|
I believe you read that wrong, please read the comments I have in the code. The point here was exiting out of the the for loop embedded in the while loop, not the if format
Although I am also interested if using if -else -if actually is faster than repetitive
if() {code(); end_if_checks();} if() {...} in my example though.
|
|
|
|
|
If u want speed, i would const the size of for your fixed string,
would safe u getting it's length each time u go for another loop in the while.
The continues u fire are at end of each if slice, and in an if else construction
it would jump out to bottom anyways, so in this case i think continue actually will be equally fast at best and else even slower.
for(unsigned int i = 0; i < StringArray.size(); ++i)
{
if(!stricmp(text+sizeof("other thing ")-1, StringArray[i]))
{
StringArray.erase(i);
break;
}
}
I normally do different, a bit slower i assume but clear
const int Sizer = sizeof("other thing ")-1;
int WalkTo = StringArray.size() - 1;
if (WalkTo >= 0)
{
const char* Check = text + Sizer;
int i = -1;
int Found = 0;
do
{
i++;
if (!stricmp(Check, StringArray[i]))
{
StringArray.erase(i);
Found = 1;
}
} while (!Found && (i < WalkTo));
}
modified 29-Feb-12 3:31am.
|
|
|
|
|
Okay, let me add a line at the prefix to clear up any confusion:
std::vector<std::string> StringArray;
The StringArray.size() gets the size of an array of std::strings, not an array of chars.
Say the StringArray was initialised to a set of usernames, in a server for example, and the command 2 could be "disconnect xxx".
|
|
|
|
|
Except that then u might want to retrieve the current size each loop what does it make it different for the rest? I see no different(new) reason to agree break is a good way to be honest.
|
|
|
|
|
The main problem is that goto statement is the only instruction in all programming languages that can change the PC (Program Counter) register in the processor
and this is not right
|
|
|
|
|
Clearly false since a whole bunch of language constructs compile into assembler/IL jump instructions.
|
|
|
|
|
I guess its just that abusing it can make source code hard to follow.
|
|
|
|
|
When I was a kid, I had a book with a BASIC program that generated mazes. I loved the game, but it was a mess of code. There were GOTOs that led straight to other GOTOs! (Check out line 780.) As an exercise when I got older, I went through and made it structured -- took days! That is why all the GOTO hate.
Anyway, using a GOTO on occasion isn't such a big deal. The problem is when it is the backbone of a complex program. And I agree with the person who said very few programmers come across a situation in which GOTO would be the preferred method.
|
|
|
|
|
Hmm, looks remarkably like a very basic finite state machine to me 8)
|
|
|
|
|
I agree on the state machine.
Each state has one subroutine for it.
Each subroutine could transition to one or more states.
Simple, concise.
How (and why) would a goto improve this?
Other thoughts
In assembly, ever high level loop is implemented with gotos/branches.
Java does not have or need a goto because they allow labeled break and continue statements. I don't think C# copied that feature (unfortunately).
|
|
|
|
|
Subroutines cause stack push pulls, the goto doesn't which makes it much more efficient. If you want your code to run in an ever shrinking hardware platform world things like that put you in front of the competition.
|
|
|
|
|
I think his point was that in the end, everything ends translated to gotos by the compiler.
|
|
|
|
|
Deep recursion could potentially stand to be replaced with a goto.
The problem as others have mentioned is that it has been heavily abused. And since it usually would only be needed under a limited set of circumstances it's better to just make it off-limits unless someone can make a compelling case for its use.
|
|
|
|
|
The key to any job is having the right tool.
If we start removing tools because people abuse them we would have to take computers away from people entirely. Just saying 
|
|
|
|
|
Yes, if you're working in a language which doesn't support tail recursion. This goto (and the argument reassignments) should be clearly commented as being a hack around tail recursion not working, though.
|
|
|
|
|
Try working on a limited stack-depth platform, such as the PIC16F1516 - your tune will quickly change when you hit the stack depth with your precious function calls. Without goto on that platform you'd be royally f***ed for anything more than the simple.
Tail recursion on a PIC: GOTO!
The worst thing about the darkness is the light at the end - DX-MON
|
|
|
|
|
I've been sitting here cogitating on this. Every switch statement that I write is just a calculated goto. The compiler takes care of all the gubbins behind the scene.
brian
a sig? i don't need no stinking sig!
|
|
|
|
|
englebart wrote: Java does not have or need a goto because they allow labeled break and continue
statements. I don't think C# copied that feature (unfortunately).
Incorrect. Not only are break and continue supported, they have been ported with slight syntax changes to VB.Net (e.g. Exit For/Loop, Continue For/Loop). I've used these features in both these environments.
|
|
|
|
|
Same for me, this is a state machine!!
|
|
|
|
|
Yep, seems like goto used to implement a simple "Case" statement to me too.
In fact, "If", "Case", "For", "While" are just patterns captured from observing the repeated use of "Goto"; I would imagine. Thereby simplifying the language so you as the read don't have to search through the connecting statements to realize the "Goto" is just implementing a "While" or "If" pattern.
Of course not all conceivable "Goto" pattern has been captured. Consequently, there are no doubt algorithms in which the "Goto" is either necessary or a simplier description than combinations of the aforementioned patterns, as rare as these may be.
|
|
|
|
|
George Dennie wrote: Of course not all conceivable "Goto" pattern has been captured. Consequently,
there are no doubt algorithms in which the "Goto" is either necessary or a
simplier description than combinations of the aforementioned patterns, as rare
as these may be.
Theoretically, ANY goto can be replaced with a finite state machine. Practically speaking, after ten years of trying I still never eliminated two goto's in a C module that did some rather hairy financial estimation at a former employer of mine, and I did eliminate the other several dozen or so that originally decorated the same module. It wasn't that it couldn't be eliminated, it was that the refactoring necessary to eliminate it was always too painful for the time we wanted to spend.
The fact is, though, that it's much easier to teach someone how a piece of structured code works than it is to teach how a piece of spaghetti code works. That same module was one evil monster to troubleshoot when it had its maximum lifetime gotos because it was not structured; I got permission to eliminate the gotos because the original guys who wrote it were gone, and even the owner/entrepeneur who'd come up with the algorithm couldn't explain exactly how the code was doing it, so any attempt to update or enhance it required hours to days of analysis first; after I got done, that time spent went down by at least 90%.
When you're not living with a piece of code but simply visit it every now and then, it does not pay to use any technique that you may not be able to understand easily a year or two later, especially if it's not your code but your employer's.
|
|
|
|