Thread: Why is goto the devil and exiting programs question.

  1. #31
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Jefff
    Would calling a function itself create some weird and dangerous itself calling loop?
    If you do not have a base case (i.e., a condition such that the function no longer calls itself, directly or indirectly) that allows the recursion to terminate, yes.

    Quote Originally Posted by Jefff
    Also this appears to run the function itself when assigning it to a variable:
    Yes. That does not assign the function to a variable. That assigns the return value of the function call to a variable.

    Quote Originally Posted by Jefff
    Then I have to use a silly if/else in the main function to decide on how to proceed. And having a clunky if/else in my main function for that just feels wrong. I am trying to keep the main function totally clean (only use it to call function), so I would like to know how to tell a function to restart itself without using goto and without calling itself again and again.
    If you religiously believe that the global main function should be so special, then define a function named say, program, call it from the global main function, and put that if statement in the program function. Frankly, I would be more concerned with creating functions that do one thing and do it well instead of creating functions that must only call other functions.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  2. #32
    Registered User
    Join Date
    Feb 2009
    Posts
    37
    Actually, having a function call itself recursively on invalid input is probably not the best method. Since you only want the instance with valid input to do anything, you may as well not be calling the others.

    A loop around displaying the possible input, and getting the input would be appropriate:

    Code:
    int input = -1; // Invalid input.
    while (input < 0 || input > 3) {
    	// Display menu:
    	cout << "1 : List Entries\n";
    	// ... other options.
    
    	// Get input.
    	cin >> input;
    }
    
    // Now you have valid input. Do something with it.
    if (input == 1)
    	// List your entries.

  3. #33
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Jefff View Post
    I found another issue where I would find goto useful, but what are the alternatives?
    This function should restart itself when an invalid menu section is selected.
    Let's think about the logic here for a second:
    We want to repeat the menu if an invalid selection is made.
    Or in other words: while the input is incorrect, repeat the menu.

    See that there? That easily translates to
    Code:
    while (input is incorrect)
    {
        show menu here;
    }
    The loops and if features of the language will allow you to do all sorts of logic. You don't need goto. You just need to understand logic and what the language offers to help you execute that logic.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #34
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    There is a case where goto is required, as the method cannot be effectively or clearly implimented using other types of loops, and that is the exception loop.

    Code:
    // some initialization code goes here
    
    while(somecondition){
    
       start:
    
       // some code goes here
    
       if(somecondition) goto start;
    
       // some code that possibly sets somecondition true
    
       }
    cannot be implimented in fewer AND easier to read lines.

    of course you could always do this -

    Code:
    while(somecondition){
       while(somecondition){
    
          // some code goes here
    
          }
       // some code that possibly sets somecondition true
       }
    for the single exception, but what if you have 2 or 3 or 20 possible exceptions. what if you need to add more exceptions later. you would end up with dozens possibly hundreds of nested while loops.

    Anyone that makes such a broad statement as 'goto is bad' is innexperienced at best. While it is generally to be avoided because it is usually not the best way to code, it has its uses and you shouldn't spend too much time worrying about trying to find some way around it.

  5. #35
    Registered User
    Join Date
    Jul 2009
    Posts
    36
    Using the while-loop inside the function did the trick.

    Code:
    void menu()	{
    
    	bool selection_invalid = true;
    
    	while (selection_invalid == true)	{
    	cout<<"#########################"<<endl;
    	cout<<"FILE I/O TEST APPLICATION"<<endl;
    	cout<<"#########################"<<endl<<endl;
    	
    	
    	cout<<"<1>List entries"<<endl;
    	cout<<"<2>Display specific entry"<<endl;
    	cout<<"<3>Create new entry"<<endl;
    	cout<<"<0>Exit program"<<endl;
    	cout<<"Select function: ";
    
    
    
    	//Get selected menu
    	int m;
    	cin>>m;
    	cout<<endl;
    
    	//Check if valid selection
    	if (m > 3 || m < 0)	{
    	cout<<"<ERROR>Invalid selection, restarting menu..."<<endl<<endl;
    	}
    	else {
    		selection_invalid = false;
    		}
    	}
    }

  6. #36
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by abachler View Post
    There is a case where goto is required, as the method cannot be effectively or clearly implimented using other types of loops, and that is the exception loop.
    You can simply use the keyword continue instead of goto.

    Code:
    // some initialization code goes here
    
    while(somecondition){
    
       // some code goes here
    
       if(somecondition) continue;
    
       // some code that possibly sets somecondition true
    
       }
    Anyone that makes such a broad statement as 'goto is bad' is innexperienced at best. While it is generally to be avoided because it is usually not the best way to code, it has its uses and you shouldn't spend too much time worrying about trying to find some way around it.
    OK, that example failed. Any other situation you can think of where goto is good/better than other solutions?
    You will not convince me (or others) unless you can provide backup to your claims on this one.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #37
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Jefff
    Using the while-loop inside the function did the trick.
    Incidentally, there is no need to write selection_invalid == true. You can just write selection_invalid, especially since selection_invalid is a bool variable. Also, you should improve your indentation, e.g.,
    Code:
    void menu() {
        bool selection_invalid = true;
        while (selection_invalid) {
            cout << "#########################\n"
                    "FILE I/O TEST APPLICATION\n"
                    "#########################\n\n"
                    "<1>List entries\n"
                    "<2>Display specific entry\n"
                    "<3>Create new entry\n"
                    "<0>Exit program\n"
                    "Select function: ";
    
            // Get selected menu option
            int option;
            cin >> option;
            cout << endl;
    
            //Check if valid selection
            if (option > 3 || option < 0) {
                cout << "<ERROR>Invalid selection, restarting menu...\n" << endl;
            }
            else {
                selection_invalid = false;
            }
        }
    }
    I took the liberty of demonstrating that adjacent string literals are concatenated for you, and of renaming m to option (i.e., use descriptive names). You probably want to change the function to return the selected option. (Also, try entering alphabetic input for the menu option to see what happens.)

    Quote Originally Posted by Elysia
    OK, that example failed. Any other situation you can think of where goto is good/better than other solutions?
    You will not convince me (or others) unless you can provide backup to your claims on this one.
    BEN10 already cited an example in post #6, though I would replace "the only" with "one" and replace "advisable" with "permissible" or "might be considered".

    Generally, I agree with abachler's point that goto should be avoided rather than completely banned, but saying that "you shouldn't spend too much time worrying about trying to find some way around it" to someone who is inexperienced is a bad idea, in my opinion. It is only when you are familiar with the rule that you can appreciate when it is time to invoke an exception to it.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #38
    Registered User
    Join Date
    Jul 2009
    Posts
    36
    Is there a reason to use \n instead of endl? I find endl or <<endl much easier to type, because to type \n on a german keyboard I have to use ALT GR + the key next to 0, while <<endl can be typed with one hand alone.

  9. #39
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Jefff
    Is there a reason to use \n instead of endl?
    Is there a reason to explicitly flush the output buffer after printing a new line? If not, then there is no point in doing so with the std::endl manipulator.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #40
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by laserlight View Post
    BEN10 already cited an example in post #6, though I would replace "the only" with "one" and replace "advisable" with "permissible" or "might be considered".

    Generally, I agree with abachler's point that goto should be avoided rather than completely banned, but saying that "you shouldn't spend too much time worrying about trying to find some way around it" to someone who is inexperienced is a bad idea, in my opinion. It is only when you are familiar with the rule that you can appreciate when it is time to invoke an exception to it.
    I do agree with all the above, but abachler's approach was particularly bad, so I was wondering if there's any "other" methods aside from the breaking out of multiple loops problems where he/she might suggest goto. Especially for C++.
    Although, maybe I formulated that post a little harshly.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #41
    Registered User
    Join Date
    Jul 2009
    Posts
    36
    Is there a reason to explicitly flush the output buffer after printing a new line? If not, then there is no point in doing so with the std::endl manipulator.
    "C++ without fear" uses this all the time, I was thinking it is the cool thing to do.

  12. #42
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,229
    I think what she is emphasizing is that, while they both print a newline, std::endl also flushes the output stream (makes sure your output goes to the console).

    For printing to terminals (consoles) they will probably behave the same, since terminals are usually line-buffered anyways (at least on *nix systems).

    If you are communicating to another program through pipes, for example, they may behave differently.

    It doesn't hurt to use std::endl everywhere. The only exception would be if you NEED the output to not be flushed... Unnecessary flushes can slow your program down a bit if you are doing A LOT of outputting, but don't worry about it for now. It's a subtle issue. Just use whichever you like.

  13. #43
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    I would postulate that in 99% of cases where people use a goto, they are simply inexperienced in thinking in terms of structured programming. When people use a goto they probably don't even realise that what they are writing is in fact just a loop etc. The big picture that say X lines of code should keep running until 'condition' is false, doesn't occur to them. They are instead thinking in terms of the small picture of "if this 'condition' is true here then I want to jump to executing from over here". It can be a failure to recognise that what they are considering to be an exceptional case is in fact the norm.

    Take for example a function that must generate a point within a unit sphere with even probability, using the rejection method. The goto person will be thinking in terms of "oh and if it ever picks a point outside the sphere, we need to go back up to here". They may even tell you "oh it's not a loop, it only needs to sometimes run again if it didn't get a satisfactory answer".
    The structured programming thinker will be thinking "We need these lines of code to run over and over while the point we pick is outside the sphere".

    There is no better result than for the "goto" thinker to adjust their thinking. Their code can only improve, both for themselves and others.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  14. #44
    Registered User
    Join Date
    Mar 2007
    Posts
    416
    Quote Originally Posted by rossipoo View Post
    Here is an illustration of how much using loops can improve the readability of code. I'll use loops and gotos to solve a simple problem, creating a multiplication table:

    Using for loops:
    Code:
    	for (int a = 1; a <= 6; ++a) {
    		for (int b = a; b <= a * 6; b += a) {
    			std::cout << std::setw (3) << b << " ";
    		}
    		std::cout << "\n\n";
    	}
    Directly converting those for loops to gotos:
    Code:
    	int a = 1;
    start_loop_a:;
    	if ( !(a <= 6)) goto end_loop_a;
    	int b = a;
    start_loop_b:;
    	if ( !(b <= a * 6)) goto end_loop_b;
    	std::cout << std::setw (3) << b << " ";
    	b += a;
    	goto start_loop_b;
    end_loop_b:;
    	std::cout << "\n\n";
    	++a;
    	goto start_loop_a;
    end_loop_a:;
    It is possible to do it using only one loop by adjusting the logic slightly, though not much more elegantly:
    Code:
    	int a = 1;
    	int b = a;
    start_loop_c:;
    	if ( !(a <= 6))
    		goto end_loop_c;
    	std::cout << std::setw (3) << b << " ";
    	b += a;
    	if ( !(b <= a * 6)) {
    		++a;
    		b = a;
    		std::cout << "\n\n";
    	}
    	goto start_loop_c;
    end_loop_c:;
    Awesome example.

    A lot of new programmers learn about goto and get all happy because it's a way to accomplish something they wanted. When really there are better/clearer alternative ways to do it, but new programmers just might not have the skill or knowledge for those other ways yet. I like to turn things around some times and ask myself how it would look to someone that did not write this code.

    Readability and self documenting code are good habits to have. Something like goto does not fall under either of those habits.

  15. #45
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    I don't think there are that many new programmers learning goto these days. Might be wrong though. In any case I don't think the example was particularly happy because I do find the goto approach readable and actually rather easy to maintain.

    The problem of code readability is of less importance here. More pertinent perhaps is code maintainability and the simple observation that the language offers better features. Better, because the language is built around the concept of structured code and we should do our best to follow the language syntactic rules, much like with any spoken language.

    Ironically Goto is a little all over C++. When you continue or break of a loop, when you case a condition, when you conditionally return of a function, etc. So any ethical or moral considerations against Goto should be pondered before bringing them into the discussion. The fact we often feel the need to alter program normal flow is the reason goto was created. We still do it today. We just have more ways of using goto and call them different names. Goto is everywhere and only a handful of programming paradigms were able to completely remove it.

    ...

    As such, I find the "Goto is evil" approach a little boring (truth is I'm not a fan of the is-evil argument for about anything programming related). More important than showing why goto shouldn't be used, is showing when goto should be used. Anyone with a few weeks of C++ will immediately learn to recognize the benefits of a structured language and doesn't need to be told against Goto. If they don't, their careers in software programming will be short and not warrant the debate. But much, much, more difficult is identifying those moments when goto can become useful.

    Start here (pdf).
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

Popular pages Recent additions subscribe to a feed