C: alternative to goto?

Discuss how to write good code, break bad code, your current pet projects, or the best way to approach novel problems

C: alternative to goto?

Post by Sharmz on Wed Jul 16, 2008 8:49 pm
([msg=7599]see C: alternative to goto?[/msg])

Ive gotten into a bad habit of using goto:
for example
Code: Select all
#include<stdio.h>
#include<string.h>
main()
{
      char c;
     int i;
     char str[]="You are correct!";
     char str2[]="You are incorrect, press enter to start over";
     char str3[]="yes";
     char str4[]="no";
     char str5[5];
     
     printf("Welcome to the quiz!\n");
     printf("There are 5 questions\n");
     printf("\n");
     printf("Please type yes or no to the questions\n");
      printf("\n");
     printf("lowercase yes and no only!\n");
     printf("\n");
     printf("If you get a question wrong the program will start over!\n");
     printf("\n");
     printf("Type enter to start\n");
     c = getc(stdin);

     
     next:
     do{
     printf("Magnum opus means great work. yes or no?\n");//question 1
     gets(str5);
     } while (strcmp (str3, str5) != 0);//correct answer is yes
     printf("\n");
     puts ("Correct answer!");
     printf("\n");
     
     printf("A paragon is a self contradictory statement. yes or no?\n");//question 2
     gets(str5);
     if (strcmp (str4, str5) != 0){ //correct answer is no
                printf("\n");
                printf("%s\n", str2);
                printf("\n");
                c = getc(stdin);
                goto next;
                }
     else{
          printf("A dystopia is a perfect world. yes or no?\n");
          }
          gets(str5);
     if (strcmp (str4, str5) != 0){ //correct answer is no
                printf("\n");
                 printf("%s\n", str2);
                 printf("\n");
                  c = getc(stdin);
                goto next;
                }
     else{
          printf("Ephemeral means lasting for a short time. yes or no?\n");
          }
     gets(str5);
     if (strcmp (str3, str5) != 0){ //correct answer is yes
                printf("\n");
                printf("%s\n", str2);
                printf("\n");
                 c = getc(stdin);
                goto next;
                }
     else{
          printf("Colonoscopy refers to a successful colony. yes or no? \n");
          }
          gets(str5);
     if (strcmp (str4, str5) != 0){ //correct answer is no
                 printf("\n");
                 printf("%s\n", str2);
                 printf("\n");
                  c = getc(stdin);
                goto next;
                }
     else{
          printf("You won! Congratulations!\n");
          printf("\n");
          printf("If you won on your first try you are smart \n");
          printf("\n");
          printf("If you took a lot of tries to win, you are smart but need to try harder\n");
          }
          printf("Press enter to exit\n");
                       
     c = getc(stdin);
     return 0;
}

What is an alternative to the goto? I seem to be using it for all my programs now....but its a bad habit.
Preferably you can show me with this code.
Thanks
"You must be the change you wish to see in the world."
-Mohandas Karamchand Gandhi
"Be nice to nerds. Chances are you'll end up working for one."
-Bill Gates
Sharmz
New User
New User
 
Posts: 41
Joined: Thu May 29, 2008 1:18 am
Blog: View Blog (0)


Re: C: alternative to goto?

Post by OneArrow on Thu Jul 17, 2008 1:56 am
([msg=7616]see Re: C: alternative to goto?[/msg])

If you find yourself using goto as a crutch, think to yourself, "what control flow statement would work better here?" If it happens infinitely until interrupted, as with a program that waits for the user to enter a certain command to quit, you're probably looking for a while loop: "while (the program isn't ready to close) { ask the user what to do, and process the request }"

On the other hand, if it's one chunk of code that you keep jumping back and forth between, consider declaring a separate function for it instead: just call the function, it'll return you to exactly where you left off once it's done. If you're doing any kind of counting, a for loop is typically what you want: "for (all values starting at 0, but less than x, adding 1 to the last number each time) { do something with the numbers as you count to x }"

Hope this helps.
OneArrow
Poster
Poster
 
Posts: 123
Joined: Thu May 22, 2008 8:26 pm
Blog: View Blog (0)


Re: C: alternative to goto?

Post by youwin on Sun Jul 20, 2008 12:18 am
([msg=7872]see Re: C: alternative to goto?[/msg])

I dont see what the big deal is with people who avoid at all costs goto statements. It has its uses and i usually dont have a prblem following code used with them. theyre great for getting out of nested loops. but for the code above you may consider using continue and break statements in one main while loop.
youwin
New User
New User
 
Posts: 2
Joined: Sun Jul 20, 2008 12:11 am
Blog: View Blog (0)


Re: C: alternative to goto?

Post by nathandelane on Mon Jul 21, 2008 7:23 am
([msg=7927]see Re: C: alternative to goto?[/msg])

Goto statements in general cause spaghetti code - if you used goto in code for a job, then your senior developer would probably pull you in for a meeting. In languages that have other flow-control statements, like loops, and functions gotos are firstly completely unnecessary, and secondly just plain bad coding. Th ONLY time that goto is okay, IMNSHO is when you have limited space to compile against, and a goto reduces the size of your program significantly. An example of this might be when you are writing a relatively large C program for a micro-controller, and the program has to fit in say 16 megabytes of space but be able to handle several MIPS commands coming at it. Anyway, if there is an alternative to goto, which in most cases there is, then you should use that alternative as much as possible over the goto statement. There ARE some programming languages that do not have loops, or they aren't very useful, OR they don't have functions (often gotos are used where a function should be written), like Microsoft's Batch scripting language, which is already being replaced by their object-oriented/functional scripting engine, PowerShell. So it is becoming less and less likely that you'll ever need a goto statement.

Why is using goto bad coding? Using goto statements is bad coding because it shows a lack of planning and ability to break code out into functions. (This is nothing against you Sharmz, in fact you realized that goto statments weren't what you needed/wanted).

Here's how I would have written your program using my experience.

Code: Select all
#include<stdio.h>
#include<string.h>

int main(void)
{
     char c;
     int i;
     char strTable[4][80] = { "You are correct!\n", "You are incorrect, press enter to start over\n", "yes", "no" };
     char questionsTable[5][80] = { "Magnum opus means great work. yes or no?\n", "A paragon is a self contradictory statement. yes or no?\n", "A dystopia is a perfect world. yes or no?\n", "Ephemeral means lasting for a short time. yes or no?\n", "Colonoscopy refers to a successful colony. yes or no? \n" };
     char answersTable[5][4] = { "yes", "no", "no", "yes", "no" };
     char userInput[5];
     
     printf("Welcome to the quiz\nThere are 5 questions\n\nPlease type yes or no to the questions\n\nlowercase yes and no only!\n\n");
     printf("If you get a question wrong the program will start over!\n\nType enter to start\n");

     while((c = getc(stdin)) != '\n')
     {
          /* Loop until the user presses Enter */
     }
     
     for(i = 0; i < 5; i++)
     {
          do
          {
               printf("%s", questionsTable[i]);
               gets(userInput); /* Need to protect against buffer overflow here */
          }
          while(strcmp(userInput, strTable[2] /* yes */) !=0 && strcmp(userInput, strTable[3] /* no */) !=0);
         
          if(strcmp(userInput, answersTable[i]) == 0)
          {
               printf(strTable[0]);
          }
          else if(strcmp(userInput, answersTable[i]) != 0)
          {
               printf(strTable[1]);
               i = -1; /* Reset i so as to start over from the top */
               while((c = getc(stdin)) != '\n')
               {
                    /* Loop until the user presses Enter */
               }
          }
     }

     printf("You won! Congratulations!\n\nIf you won on your first try you are smart \n\nIf you took a lot of tries to win, you are smart but need to try harder\n");
     printf("Press enter to exit\n");

     while((c = getc(stdin)) != '\n')
     {
          /* Loop until the user presses Enter */
     }

     return 0;
}


Also you'll see that I use this code three times in the program:
Code: Select all
while((c = getc(stdin)) != '\n')
{
     /* Loop until the user presses Enter */
}


Using a piece of code more than twice makes it a good candidate for a function, so I should probably pull this out into its own function.

youwin wrote:theyre great for getting out of nested loops


If you need to use a goto or any method to get out of a nested loop that is not in some way part of the loop, then you probably need to rethink your program and make it more dependent on input, and probably reduce the number of nested loops you have - a lot of nested loops might be a sign that you need to make a recursive method.

Just my thoughts.
Me, Nathandelane, Highly influential to Hackerdom, Premature Optimization=http://c2.com/cgi/wiki?PrematureOptimization
User avatar
nathandelane
Poster
Poster
 
Posts: 204
Joined: Thu Jun 26, 2008 11:26 am
Location: Utah
Blog: View Blog (0)


Re: C: alternative to goto?

Post by Sharmz on Mon Jul 21, 2008 3:58 pm
([msg=7956]see Re: C: alternative to goto?[/msg])

Thanks a lot Nathan!
-Sharmz
"You must be the change you wish to see in the world."
-Mohandas Karamchand Gandhi
"Be nice to nerds. Chances are you'll end up working for one."
-Bill Gates
Sharmz
New User
New User
 
Posts: 41
Joined: Thu May 29, 2008 1:18 am
Blog: View Blog (0)


Re: C: alternative to goto?

Post by YACH on Wed Jul 23, 2008 4:25 pm
([msg=8091]see Re: C: alternative to goto?[/msg])

goto can be useful, if you need to break out of a nested loop. Let's say you had a game like this where ESC would isntantly break you out of the game loop:
Code: Select all
while(Running)
{
    while(!GameOver())
    {
          char kbinput;
          while(GetInput(&kbinput))
          {
                      if(kbinput==KEY_ESCAPE)
                              goto escape;
           }
     }
}
escape:
return 0;

This is very rare though. If you've ever written assembly language, you will come to know that ANY loop can be represented with a goto (known as a jump). For example, here is a DOS function I wrote that prints a null-terminated string:
Code: Select all
printsz:
   mov dl,[si] ; get the character at si
   cmp dl,0 ; check if we got 0
   jz done ; if so, we're done
   inc si ; if not, increment si
   mov ah,02h ; we want to print a character to the screen
   mov al,[si-1] ; get the previous character printed
   int 21h ; call the function
   jmp printsz ; go back to the beginning of the loop
done:
        ret

The jz could be compared to if(dl==0) goto done;. In assembly that's the ONLY way to do loops. (I think there is a loop mnemonic though, but it is similar to a goto).
YACH
New User
New User
 
Posts: 1
Joined: Wed Jul 23, 2008 4:14 pm
Blog: View Blog (0)


Re: C: alternative to goto?

Post by OneArrow on Wed Jul 23, 2008 5:02 pm
([msg=8097]see Re: C: alternative to goto?[/msg])

YACH wrote:goto can be useful, if you need to break out of a nested loop.


There are more elegant ways to break out of a nested loop. In fact, the break keyword comes to mind...
OneArrow
Poster
Poster
 
Posts: 123
Joined: Thu May 22, 2008 8:26 pm
Blog: View Blog (0)


Re: C: alternative to goto?

Post by mAg1c_HaNd5 on Thu Jul 24, 2008 4:48 pm
([msg=8189]see Re: C: alternative to goto?[/msg])

I think that putting it in different functions is the best way. It is easier to read and if you ever expand your project it makes everything much easier.
mAg1c_HaNd5
New User
New User
 
Posts: 29
Joined: Thu Jul 24, 2008 4:35 pm
Blog: View Blog (0)


Re: C: alternative to goto?

Post by sharpskater69 on Fri Jul 25, 2008 2:08 am
([msg=8226]see Re: C: alternative to goto?[/msg])

There are basically 2 types of people when it comes to "goto":
a)the ones who know it's apart of the language so obviously it has some use, but more times than not has a workaround
b)the ones who are religious about it's use and say any use is misuse

You can add another loop, make the function recursive and make a recursive call, or use another jump statement like others have mentioned. As for breaking out of nested loops in a function, you can just use "return", otherwise "return 0".

what if you have a huge function with several if/else statements and readability is one of the last things you want to be burdened with? There's a good time to use goto. Jumping to another part of the program when you could just do one of the alternatives easily is how goto got it's bad name. Hope this can help you.
sharpskater69
New User
New User
 
Posts: 34
Joined: Tue Apr 22, 2008 4:10 pm
Blog: View Blog (0)


Re: C: alternative to goto?

Post by codz30 on Fri Jul 25, 2008 3:50 am
([msg=8232]see Re: C: alternative to goto?[/msg])

use of while and for loops, goto can be used as a exit it out of huge loops with masses of if and else statments, to save rewriting 'continue' and 'free(memory)' etc.
codz30
New User
New User
 
Posts: 2
Joined: Fri Jul 25, 2008 3:43 am
Blog: View Blog (0)


Next

Return to Programming

Who is online

Users browsing this forum: No registered users and 0 guests