Lets see how we can replace an ugly goto with an elegant structured programming constructs.
Given an unstructured loop line1: printf("Dijkstra sucks cocks in hell.\n"); goto line1;
Without sacrificing any expressiveness, we can refactor the above code into: line = 0; while (line++ > 0) { switch(line) { case 1: printf("Dijkstra sucks cocks in hell.\n") break; case 2: line = 1; break; } }
Not only did we killed goto, but also gained a way to address lines of code dynamically. I.e. we can compute the next value of "line" variable.
I also noticed something disturbing while testing this on some simple C code of mine: While scanning the source for those nasty goto statements, I noticed from analysis of intermediate output that many times my innocent, structured if statements were being silently transformed into goto directives by the compiler!
This was clearly unacceptable, but your fix saved the day.
From this:
static void fizzbuzz(int n) { int i; for (i = 1; i < n; ++i) { if ((i % 3 == 0) && !(i % 5 == 0)) { printf("Fizz\n"); } else if (!(i % 3 == 0) && (i % 5 == 0)) { printf("Buzz\n"); } else if ((i % 3 == 0) && (i % 5 == 0)) { printf("Buzz\n"); } else if (!(i % 3 == 0) && !(i % 5 == 0)) { printf("%d\n", i); } } }
To THIS!!!
static void fizzbuzz(int n) { int line = 1; int computed_line; int i; while (line < 200) { switch (line) { case 10: i = 0; break; case 20: i = i + 1; break; case 21: computed_line = 95; break; case 30: if (i > n) line = 200; break; case 40: if (i % 3 == 0) computed_line += 30; break; case 50: if (i % 5 == 0) computed_line += 50; break; case 60: line = computed_line; break; case 100: printf("%d\n", i); line = 15; break; case 130: printf("Fizz\n"); line=15; break; case 150: printf("Buzz\n"); line=15; break; case 180: printf("FizzBuzz\n"); line=15; break; }
line++; } }
There are still if statements, and therefore still goto statements in the result, but they are safely and structurally bound by the beauty of the while-switchgoto-cleansing DESIGN PATTERN!
Name:
Anonymous2014-02-09 17:19
It's funny because the dumbass stupid "refactoring" it actually as stupid as the original code.
Name:
Anonymous2014-02-09 17:42
>>5 It's funny because it doesn't work. line++>0 is false the first run through.
>>6 If it got past there, it would also spin endlessly on setting line1=1, not on the printf.
Name:
Anonymous2014-02-11 17:52
This is awesome!
bad int password_correct = 0; char big_enough_buffer[10]; do { puts("enter password to continue"); gets(big_enough_buffer) if (strcmp(big_enough_buffer, PASSWORD) == 0) password_correct = 1 } while(!password_correct)
good int line = 0; int password_correct; char big_enough_buf[10]; while (line++ < 200) { switch (line) { case 20: password_correct = 0; break; case 30: puts("enter password to continue"); break; case 40: gets(big_enough_buffer); break; case 50: if (strcmp(big_enough_buffer, PASSWORD) != 0) line = 69; break; case 60: password_correct = 1; break; case 70: if (!password_correct) line = 29; break; } }
Oh boy! I've got an idea that might improve this! Check this out:
#define PROGRAM(CODE) \ int line = 0; \ while (line < 999999) { \ switch (line) { \ CODE \ } \ line++; \ } #define LINE case #define GOTO(LINE) line = (LINE-1); #define ENDLINE ;break;
Pretty awesome, I know =)
To make things even more clear: #defin DO : #define PLEASE /* just to be polite */
Now we can do our above code like this:
int password_correct; char big_enough_buf[10]; CODE( LINE 10 PLEASE DO password_correct = 0 ENDLINE LINE 20 PLEASE DO puts("enter password to continue") ENDLINE LINE 30 PLEASE DO gets(big_enough_buffer) ENDLINE LINE 40 PLEASE DO if (strcmp(big_enough_buffer, PASSWORD) != 0) GOTO(60) ENDLINE LINE 50 PLEASE DO password_correct = 1 ENDLINE LINE 60 PLEASE DO if (!password_correct) GOTO(20) ENDLINE
>>11-kun should get right on learning INTERCAL. It's poised to shift a few paradigms and make huge strides in mindshare: http://intercaloninterstates.org/
concrete jungle where dreams are made, oh There's nothing you can't do, now you're in New York
Name:
Anonymous2016-11-10 18:15
#include <stdio.h> #define BE = #define IS = #define EQU == #define MOD % #define BEGIN int #define PROGRAM main() { #define PLUS + #define LET int #define LINE(n) ;line##n: #define IF if( #define THEN ) #define GOTO(n) goto line##n #define END return 0;} #define PRINTN(n) printf("%d",n) #define PRINTS(s) printf("%s",s) #define NEWLINE printf("\n") #define NOT(n) !(n) #define OR ||
BEGIN PROGRAM LINE(10) LET I BE 1 LINE(20) IF I EQU 101 THEN GOTO(130) LINE(30) IF I MOD 3 EQU 0 THEN GOTO(70) LINE(40) IF I MOD 5 EQU 0 THEN GOTO(90) LINE(50) IF NOT(I MOD 5 EQU 0 OR I MOD 3 EQU 0) THEN PRINTN(I) LINE(60) GOTO(100) LINE(70) PRINTS("FIZZ") LINE(80) GOTO(40) LINE(90) PRINTS("BUZZ") LINE(100) NEWLINE LINE(110) I IS I PLUS 1 LINE(120) GOTO(20) LINE(130) END