Goto Statements

So I've always heard goto statements are "bad" because they make it difficult to read code...But what if it makes it easier...

I mean look at the code bellow...it seems better then adding a flag and then saying while (flag false)...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void userLogin() {

string userName;
string password;

userLogin:
cout << "User Name:"
cin >> userName;

cout << "Password"
cin >> password

...check against database

...if false GOTO userLogin;
...else continue...
}
It is much better to write

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void userLogin() {

string userName;
string password;

do
{
   cout << "User Name:"
   cin >> userName;

   cout << "Password"
   cin >> password

...check against database

} while ( some condition is false );

...continue...
}
Last edited on
it seems better then adding a flag and then saying while (flag false)...


It isn't. You think it is because you wrote the code so you understand it perfectly. You are not writing code to communicate to yourself. The source code is for communicating to anyone else who ever has to look at the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void userLogin() {

string userName;
string password;

bool loginCorrect = false;

while (!loginCorrect)
{ 
  cout << "User Name:"
  cin >> userName;
  cout << "Password"
  cin >> password
 // if correct, loginCorrect = true;
}


This code clearly contains a loop, so a reader can see the looping behaviour straight away. The condition of the loop is clearly identifiable. The flow of the program is clear.

If I see this in the middle of some code:

userLogin:

I then have to search through all the code to find all the goto that lead there. There could be one. There could be lots. I have to go looking. With the loop, it is clear straight away exactly how the loop is triggered.

Now imagine this in code containing multiple nested loops. goto quickly becomes a confusing, difficult mess.
Last edited on
It just feels so tedious defining a flag and having the extra loop...

I mean in assembly branches and jumps are key elements, I figured why the not in C! Seriously I think my code is nicer. But hey, if the industry standard is no "goto"'s then I won't use them...
It just feels so tedious defining a flag and having the extra loop...


Compare that to the tedium of having to go through ten thousand lines of spaghetti code written a decade ago by someone who also wanted to use only goto.

I mean in assembly branches and jumps are key elements, I figured why the not in C!


One of the reasons C exists is so that we don't have to build spaghetti code. Spaghetti code is what we're trying to get away from.
Last edited on
Well, many situations where goto is tempting could be replaced with a loop, for (;;) for example, and using break; and continue; statements. It's unfortunate there's no 'infinite loop' syntax more appropriate than for (;;) because it looks ugly, but I suppose that's not the most important thing.
I guess because I am working on a small project I don't see the impact of a "goto" but if you say it's good practice then I'll do it :)

Thanks
closed account (o1vk4iN6)
I think a do while statement is more appropriate as you don't need to check the first condition but i guess it just comes down to personal tastes. You may think you code is nicer because it is only 3 lines of code and you can see everything all at once but imagine having to go through 500 lines of code which has 10 loops. Yah, not so pretty anymore is it. Having to define a label for each of those is more tedious then defining flags at that point. I also don't see what's more tedious about defining a flag than defining a label, in your example.
Avoid defining flags, compared to using break and continue!
+1 @ xerzi.

The do/while loop is the best construct for this, IMO

Also you do not need a flag. Quite the opposite... with the goto approach, you have to pick a unique label name (you may find yourself with ugly, confusing names like 'loop1:', 'loop2:', etc), whereas with do/while you do not have to pick a name... the scope itself is enough to identify it.

1
2
3
4
label:
  code();
  if( condition )
    goto label

is the same as:
1
2
3
4
do
{
  code();
}while(condition);


The latter is more easily recognized by most people.

When you see a do statement, you immediately know some things:

1) You know the code is entering a loop. You do not necessarily know this when you see a label: statement. With a label, maybe the program jumps there from earlier in the function... or maybe the label is unused.

2) the code inside the loop is easily identifiable because it's within the following {code block}. This is actually huge.

Code blocks greatly improve clarity and organization. They also limit scope, which also helps keep things easy to follow. With a do/while loop, you can quickly see the entire loop because of the {block}.

With label/goto, you can't. Not only because of the lack of indentation and/or {code block}, but also because there's no scope limitation. There might be several gotos at various points in the function that jump to that label. You have no way of knowing without reading the entire function.
Last edited on
I tend toward using a simple while and a break. I think this is fairly obvious.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void userLogin()
  {
  string userName;
  string password;

  while (true)
    {
    cout << "User name: ";
    getline( cin, userName );

    cout << "Password: ";
    getline( cin, password );

    Hash( password );

    if (Validate( username, password ))
      break;

    cout << "Invalid username/password combination.\n";
    }
  }

My $0.02.
Topic archived. No new replies allowed.