Exit y/n coding

Pages: 12
How to make a program ask for this when its finished executing: Exit? (y/n) i got this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
int Exit() {
    char exit;
    cout << "\n\n";
    exitloop:
    cout << "Stoppen? (y/n)" << endl;
    cin >> exit;
    
    switch (exit) {
           case 'y':
                return 1;
                break;
           case 'Y':
                return 1;
                break;
           case 'n':
                return 0;
                break;
           case 'N':
                return 0;
                break;
           default:
                goto exitloop;
                break;                
    } 
}


In the main it gets called like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main()
{
    float lengte, breedte;
    float oppervlakte, omtrek;
    lengte = 0;
    breedte = 0;
    oppervlakte = 0;
    omtrek = 0;

    cout << "lengte: ";
    cin >> lengte;
    cout << "breedte: ";
    cin >> breedte;
    cout << "\nde oppervlakte is: " << berekenOppervlakte(lengte,breedte);
    cout << "\nde omtrek is: " << berekenOmtrek(lengte,breedte);    

    if(Exit() == 1)
      return 0;
    if(Exit() == 0)
      main();  
}



If i run the program, it works fine. But in the end it asks: Exit? (y/n) when you do y it shuts down like it should, when you press n, you have to input twice, like this:

Exit? (y/n)
n
Exit? (y/n)
n

then it executes main() again... why do you have to do n twice and y only once? help please, thank in advance
1
2
3
4
5
   
if(Exit() == 1)
  return 0;
else 
  main();


Will fix it.

Note: You should never, ever, every use goto exitloop;. Goto's a VERY bad practice.

Try something like:

1
2
3
4
5
6
7
8
9
10
11
12
bool exit() {
 char exit;

 do {
  cout << "Stoppen? (y/n): " << endl;
  cin >> exit;
  if ( (exit == 'Y') || (exit == 'y') )
    return true;
 } while ( (exit != 'N') && (exit != 'n') );

 return false; // N or n was pressed
}
Actually, the goto isn't such a grievous error considering he's recursing on main(). Please don't do that. (Your C++ compiler shouldn't let you do it anyway.) Use a loop instead.
1
2
3
4
5
6
7
8
9
10
11
12
int main()
  {
  do {
    float lengte, breedte;

    // The rest of your code goes here...

    }
  while (!Exit());

  return 0;
  }


Enjoy.
No no no. goto is severely frowned upon. The theory is that if you must use a goto, then you are obviously not good enough to be a professional developer. I have actually been asked when it's good to use a goto in an interview, the answer is never.

There should never be any reason for a goto. If you find yourself using one, then you need to refactor your code.
Here's a rhetorical question; if goto should never be needed and should never be used, why it it there?
Last edited on
I didn't disagree that refactoring into a loop is the right thing to do, but I think this is the first time I'll disagree with you [edit]Zaita[/edit] (your last two statements) on principle.

Beware of always/never rules, and dummies interviewing with a list of them in hand.

Goto exists (and remains in the language) because it has its place. A very, very, very small place, but a valid one non-the-less.

I've been hashing this one on several forums lately so my tired brain doesn't want to get too deep into it, but the correct rule is to program so that your code is clear, short, and easily maintainable. The Goto Hater's Club began back when structured programming came into vogue (mid to late 60's) and new programmers were taught to despise goto with a rabid, frothing passion so that they would use the new structured programming paradigm instead of writing horrendous, bit-twiddling code.

The problem with this blind bias is that while goto is correctly identified as encouraging poorly-structured code, it steals focus from the real source of bad code: bad programmers.

Now before anyone posts a reference to Dijkstra's "Go To Statement Considered Harmful" here it is.
PDF: http://www.cs.utexas.edu/users/EWD/ewd02xx/EWD215.PDF
HTML: http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_Harmful.html

And before anyone posts a reference to Knuth's "Structured Programming With Go To Statements" as a supposed rebuttal, here it is.
PDF: http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf
HTML: (sorry, couldn't find one on a quick Google. If I do I'll edit this.)

Before commentary, people, please please re-read both articles. You'll learn that (1) Dijkstra didn't hate GOTO, and (2) Knuth didn't disagree with Dijkstra.

Finally, before anyone posts that goto is the root of all evil, consider this (relatively) recent study (published in 1996): "Where Does GOTO Go To?":
http://citeseer.ist.psu.edu/148906.html
http://www.springerlink.com/content/mg1l4u7554004314/
(one of those links ought to work for you).

Don't hate the hammer when you hit yourself in the hand.

I'll finish by repeating what I've said elsewhere: Don't hate GOTO. Hate bad programming. And teach newbies the difference.
Last edited on
Duoas,

Nicely said!
Urrgh I have to read :P

Ok. goto does exist in C++, yes. But that doesn't mean it should be used. Unfortunately, there are languages out there that do facilitate the use of goto statements. C++ should not be one of them.

For example. VBScript uses goto statements for error conditions. This is sufficient because they do not have any valid exception handling. JScript has exception handling and should be used instead.

I would follow this quote: Other issues are clearer: garbage collection is a good idea; goto is a bad idea. said by James Gosling (Credited Inventor of Java).

Gijkstra makes some good points. goto does promote bad (lazy) code development. It's a bloody nightmare to maintain any reasonable application embedded with goto statements. Especially in C++.

"Where does GOTO Go to?". Based on Ada95 :P.

I would be interested to see a valid use of goto in C++. I for one have been asked when a goto should be used in an interview (by very talented developers). The correct answer to them was never. I have never used a goto in C++, and god-forbid never will.

I always hate bad programming, don't you worry about that :P
Rebuttals

C++ should/should not stuff is opinion.

Comparisons with other languages don't make valid arguments for the structure of C++. However, for languages in general, existing need or propriety makes a pretty powerful argument.

Mr. Gosling also made emacs popular by coding and improving it in C (originally called "gosmacs") at my University: Rutgers. I believe he has since had some (minor) misgivings about his statement on gotos, but I don't care enough to dig anything up. If you care, though, you can also dig up statements by Kernighan, Wirth, Stroustrup, Torvalds and others where they indicate that there is no need to kill goto, and they have no interest in fighting over it.

(Personally, I think Gosling's original antithesis to jumping constructs has had a ruinous effect on Java's design. It is a pain to use and I'll avoid it if I can. Personally speaking.)

Goto doesn't promote anything. Its presence does encourage lazy programmers to be lazier, but that is not sufficient reason to attack the goto. Attack the moronic programmer.

Ada95 is a highly-structured, modern programming language.


Two valid uses of goto

Number one:
1
2
3
4
5
6
7
8
9
10
11
for () {
  for () {
    for () {
      for () {
        goto get_me_the_heck_out;
        }
      }
    }
  }
get_me_the_heck_out:
/* do more stuff here */

Anyone who argues that such as the above can't happen is arguing that 123 Revolutionary Lane, Bosnia doesn't exist, never existed, and never will exist, just because he's never seen it. That's not the mark of an excellent programmer. Just an arrogant one, no matter how good he may generally be. Such structures actually are useful on the rare occasion.

Number two:
1
2
3
4
5
6
7
while ()
  switch (quux) {
    case fooey:
      goto get_me_out_now;
    }
get_me_out_now:
/* do more stuff */

This happens much more frequently than the last.


Arguments against the examples

The standard arguments against both of these are:
1. put some #@!?^$ boolean flags in there and test against them
2. use an exception or some other unwinding construct (it's "safer")

Flaggy code
Use of extraneous boolean variables produces what is known as "flaggy code," so-called because it is encumbered by a lot of "flag" variables (booleans and like constructs --or even worse, bitmaps) that the programmer has to wade through to see the actual structure of the code. I prefer clear reading code to extraneous constructs just to dance around using a goto.

Exceptions and other unwinding constructs
People get fanatic over goto, but things like switch, break, and continue sail right over their heads. Functions are a form of goto. Exceptions (which are a special case of continuation), and things functional programmers like myself like: continuations and closures are yet again fancy wrappers for gotos. In short, everything the computer does is ultimately based on the goto, even on an electronic level.


So how do we abolish bad code if we don't abolish goto?

The purpose of higher-level constructs isn't to abolish the goto, but rather to provide a better abstraction as an end to better organized and more maintainable code, and to assist the programmer in managing closures/frames. [quoting myself again]

The mark of superior programmers isn't a blind bias against specific constructs or always/never do things "this way" rules. It is a higher level of thinking to organize not the syntactic concerns of language X, rather his own thoughts into a lucid construct -- which is the ultimate goal and fruition of quality programming.


@Zaita
I actually think you are a good programmer, and I enjoy posting here with you, so please don't take my comments as any attack on you at all.

I don't really care what those fellows you interviewed with think. Who do they think they are? To proclaim all truth about how to think (program) is pure hubris, and undoubtedly beyond their qualifications. To have an opinion is one thing. To deny the validity of other's opinions is another. And to stand up and make a fuss about something experts in the field consider barely worth noticing is, well, silly. (/me counts how much I've written here...)

I am not alone in my belief that to abuse structures like exceptions or otherwise introduce extra code just to avoid the use of a goto is a pretty cavalier way to spend your employer's time and money --particularly when it can be better spent thinking about the actual meaning of the code.

I write goto-free code all the time. I've used it maybe three or four times in twenty years. But when I have used it, I used it because it was the best choice for the job --producing the cleanest, most readable, maintainable, and smallest code given the alternatives. In each case I could have figured out some other convolution to avoid it, but only at the expense of code size and complexity.


So, Duoas, by your own definition you are silly, right?

Perhaps... *sheepish grin*

The reason I spend so much time on this isn't just to defend some poor, defenseless goto out in the big, bad world.

Rather, it is so that you, dear reader, can begin to escape being "out of the box" (which is a code-phrase for people firmly stuck deep down inside "the box" so that they can feel good about themselves). Forget silly "always this" and "never that" and "hate this" rhetoric. Think about what it is that your code is actually doing, and how it is organized to do it. The process is not so much programming the computer --it is programming your own mind to understand a transformation. The more clear your own understanding, the clearer and more maintainable your own code becomes.

--Michael
DiZasteR:

Just a little extra info... you didn't have to go through the whole

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
switch (exit) {
           case 'y':
                return 1;
                break;
           case 'Y':
                return 1;
                break;
           case 'n':
                return 0;
                break;
           case 'N':
                return 0;
                break;


in fact to make you life easier insert a toupper statement...

1
2
3
4
5
6
7
8
9
10
exit = toupper(exit);

switch (exit) {
           case 'Y':
                return 1;
                break;
           case 'N':
                return 0;
                break;


this way you wont have to worry about anyone inputing a lowercase, and your program wont know what to do :)
thank for all the help, well im a real beginner ( started like 2 days ago with c++ ) so thanks for all the info, i didnt yet know the toupper thing
something else:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <cstdlib>
#include <iostream>
#include <math.h>
#include <string>
#include <sstream>

using namespace std;

double Pythagoras(double a, double b) {
      double c, res;
      c = a * a + b * b;
      res = sqrt(c);
      return res; 
}

int Exit() {
    cout << "\n\n";
    char exit;
    do {
        cout << "Stoppen? (y/n)" << endl;
        cin >> exit;
        cout << "\n";
        if((exit == 'y') || (exit == 'Y'))
          return 1;
    } while ((exit != 'n') && (exit != 'N'));
    return 0;      
}

int main() {
    string input;
    input = "";
    double a,b;
    a = 0;
    b = 0;
    cout << "a = ";
    getline(cin, input);
    stringstream(input) >> a;
    cout << "b = ";
    getline(cin, input);
    stringstream(input) >> a;
    cout << "\nc = " << Pythagoras(a,b) <<endl;    
    
    if(Exit() == 1)
      return 0;
    else
      main();  
}


For some reason it doesnt do the thing i want it to do, its supposed to calculate c if you input a and b, but it doesnt. Also, if i pick no when i asks quit, it goes like this:


Stoppen? (y/n)
n
a = b = ...


Then you just have to fill in b, and c will be equal to b

any help? i cant think of anything im doing wrong

EDIT: tried swapping res = sqrt(c); with res = pow (c,0.5); but no succes. Also, whatever number a is, c seems to be always equal to b
Last edited on
You want it like this?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <cstdlib>
#include <iostream>
#include <math.h>

using namespace std;

double a,b,c,res;

double Pythagoras(double a, double b) {
      double c, res;
      c = (a * a) + (b * b);
      res = sqrt(c);
      return res; 
}

int main() 
{
    char exit;
    do 
    {
        a = 0;
        b = 0;
        cout << "a = ";
        cin >> a;
        cout << "b = ";
        cin >> b;
        cout << "\nc = " << Pythagoras(a,b) <<endl;
        cout << "Stoppen? (y/n)" << endl;
        cin >> exit;
        exit = toupper(exit);
    } while (exit != 'Y');   
}

or do you need it to have that exit procedure?
thanks man, i didnt think about it that way :) and no i dont explicitly need that
Cool :)
Well said Duoas :)

I will say that for both of your examples of valid use for goto I would've abstracted those loops into separate functions. The goto would've been replaced by a return statement. But thats semantics.

What I think is worse than goto, is using exceptions to control normal flow. But lets not get started on that haha.
Agreed 100%.

No need to use a goto when you can make the code cleaner with functions.

BTW, have you seen Grey Wolf's Sudoku challenge?
I have :D
I was actually looking at algs the other-day relating to solving Sudoku. I am working on a spatial population modeling application, so I was curious about some spatial algs to see how the logic was applied.
Not sure how I missed this thread otherwise I'd have said my piece earlier. Now I see Duoas has stolen my thunder. The only thing I have to add to what has already been said is that the only place I have used goto is in Linux drivers, not because it was necessarily the best construct to use but because it seems to be a coding convention to use them in kernel code. People reading driver code expect to see them and if you do something completely differently to everyone else in any context it causes maintenance problems.

The point I am trying to make here is if there are coding conventions in place follow them, whether you agree with them or not. If you don't like them, get them changed, don't do your own thing just to prove a point.
Linux Kernel drivers are done in C, not C++ correct?
Pages: 12