GOTO command

I’m trying to use the GOTO command but all the examples I found are just a few lines of code that they don’t really work.

Can anybody fix this in order to work. I don’t really care what the code does. Just a working example of GOTO.

btw, why most of the examples in the reference pages are so bad? :frowning:

test = 0; //---------change this value

byte r;
byte g;
byte b;
void setup() {
  Serial.begin(9600);
}

void loop() {
  for (r = 0; r < 255; r++) {
    for (g = 255; g > -1; g--) {
      for (b = 0; b < 255; b++) {
        if (test > 250) {
          goto bailout;
        }
        Serial.println("do something");
      }
    }
  }

bailout:
  Serial.println("works");

I'm trying to use the GOTO command

Stop right now

Forget that you ever knew that the goto command existed
Using goto can produce spaghetti code that is difficult to debug
There is never any need to use the goto command, certainly with your level of experience

That code doesn’t compile so there’s no chance that it’s a working example of the use of goto, which by the way is a statement, not a command.

Pete

I agree with @UKHeliBob - just in case you thought his was an isolated opinion.

...R

UKHeliBob:
Stop right now

Forget that you ever knew that the goto command existed
Using goto can produce spaghetti code that is difficult to debug
There is never any need to use the goto command, certainly with your level of experience

I read that is not a good idea to use the GOTO but for my skill level I don’t see another option.

jucasan:
I read that is not a good idea to use the GOTO but for my skill level I don’t see another option.

there are always so many ways to do something in programming…

byte test = 0; //---------change this value

byte r;
byte g;
byte b;
void setup() {
  Serial.begin(9600);
}

void loop() {
  bool bailout = false;
  for (r = 0; r < 255; r++) {
    for (g = 255; g > -1; g--) {
      for (b = 0; b < 255; b++) {
        if (test > 250) {
          bailout = true;
          break;
        }
        Serial.println("do something");
      }
      if (bailout) {
        break;
      }
    }
    if (bailout) {
      break;
    }
  }

  if(bailout) {
    Serial.println("works");
  }
}

Is byte signed or unsigned?

Pete

^^ unsigned

Thanks BullDogLowell !!

When will this ever be false?

g > -1

Pete

Jobi-Wan:
^^ unsigned

While your answer is correct and appreciated I suspect you missed the point. I believe @el_supremo's rhetorical question was directed specifically to @BulldogLowell to bring his attention to a datatype issue in the code he posted. In the best case the snippet is confusing. In the worst case the for-loop is unbounded.

Indeed.

Pete

In what way does your example NOT work? I mean, it’s got some minor syntax errors (no type for test, no closing brace for loop), and some logic errors (the “bailout” code will be reached after the loop finishes as well as when the goto works. and the for loop limits/types are questionable), and it probably all gets optimized away by the compiler, but the “goto” itself is about right.
Here’s a corrected version that actually does something…

byte r, g, b;
void setup() {
  Serial.begin(38400);
}

void loop() {
  for (r = 0; r < 10; r++) {
    for (g = 10; g != 0; g--) {
      for (b = 0; b < 10; b++) {
        if (Serial.read() > 0) {
          goto bailout;
        }
        Serial.println("do something");
      }
    }
  }
  Serial.println("\n\n ***********  End of Loop *********\n");
  delay(500);
  return;

bailout:
  Serial.println("\n========= Bailout works ===========");
  delay(1000);
}

jucasan:
I read that is not a good idea to use the GOTO but for my skill level I don't see another option.

Write your program as a series of functions. Have a look at Planning and Implementing a Program

...R

Thank you westfw!

That is what I’m looking for. A simple use of GOTO.

int testValue = 900;   //-----------------------------------------------------change

int b;
void setup() {
  Serial.begin(9600);
}

void loop() {

  for (b = 0; b < 100; b++) {
    if (testValue > 100) {     //----------------------------------------------
      goto bailout;
    }
    Serial.println(b);
  }

  Serial.println("\n\n ***********  End of Loop *********\n");
  delay(500);
  return;

bailout:
  Serial.println("\n========= Bailout works ===========");
  delay(1000);
}

Leaving aside the fact that you don’t modify test in this loop and it will never be >250, there’s a couple of ways to treat this.

Any code with goto can be written without goto. Theoretically - I think Wirth proved this as a mathematical fact. But sometimes, using a goto makes a lot of sense. To rewite this without goto, you need to check the condition in each loop:

void loop() {
  for (r = 0; r < 255 && test <= 250; r++) {
    for (g = 255; g > -1 && test <= 250; g--) {
      for (b = 0; b < 255 && test <= 250; b++) {
        Serial.println("do something");
      }
    }
  }

  Serial.println("works");  
}

Using a goto is clearer and neater.

Java supports breaking out of neeply nested loops, C++ doesn’t.

Another way to do this is to make use of the behaviour of the return statement:

void loop() {
  findSolution();
  Serial.println("works");
}

void findSolution() {
  for (r = 0; r < 255; r++) {
    for (g = 255; g > -1; g--) {
      for (b = 0; b < 255; b++) {
        if (test > 250)
          return;
        Serial.println("do something");
      }
    }
  }
}

But this is something of a hack: the loops possibly don’t really belong in a separate function. The goto is neat, makes sense, and is not “spaghetti code”. I used to code BASIC back in the 80’s, I know what spaghetti code actually looks like. This isn’t - it’s simply exiting out of a deeply nested loop.

I don’t see another option.

Perhaps something like this. (I don’t think that ‘we’ on the arduino forums recommend functions nearly enough. This is a case where they help, aside from the usual “readability” reasons.)

byte r, g, b;
void setup() {
  Serial.begin(38400);
}

void loop() {
  if (rgbloop()) {
    Serial.println("\n\n ***********  End of Loop *********\n");
    delay(500);
  } else {
    Serial.println("\n========= Bailout works ===========");
    delay(1000);
  }
}

byte rgbloop() {
  for (r = 0; r < 10; r++) {
    for (g = 10; g != 0; g--) {
      for (b = 0; b < 10; b++) {
        if (Serial.read() > 0) {
          return 0; // Bail out
        }
        Serial.println("do something");
      }
    }
  }
  return 1; // return success
}

I've submitted a pull request to fix the bug in the goto example code:

jucasan:
btw, why most of the examples in the reference pages are so bad? :frowning:

I don't know, but it's easy enough to fix. You can submit fixes or bug reports to the reference-en repository, which contains all the Arduino Language Reference content. The Arduino team is pretty good about merging pull requests to that repo in a timely manner. For more information, see:

If you don't have a GitHub account, or want to discuss potential changes first here on the forum, then please do create a thread here.

Thank you all of you guys.
I’m working to make a RGB strip controlled by a joystick.The xPosition controls the “program” (colors and sequence) and the yPosition controls the intensity. This part needs to be implemented yet.

It might not be the cleaner code, I’m sure there are better ways to do this but is working and eventually can improve the code.

Needed the GOTO in order to get out of the loops without delay when I move the joystick.

void switch_to_value_100 ()
{
  bool bailout = false;
  for (i = 0; i <= 255; i ++)
  {
    analogWrite(ledR, i);
    analogWrite(ledG, LOW);
    analogWrite(ledB, LOW);
    Serial.println(" ");
    Serial.print(programSelector);
    Serial.print(" Red Transition ");
    //    Serial.print(" i= ");
    //    Serial.print(i);
    xPosition = analogRead(xPin);
    if (xPosition >= 540) {     // bail out on sensor detect
      i = 0;
      programSelector = programSelector - 1;
      
      goto bailout;
    }
    if (xPosition <= 480) {     // bail out on sensor detect
      i = 0;
      programSelector = programSelector + 1;
      
      goto bailout;
    }
  }
  delay(1000);
  for (i = 255; i >= 0; i--) {
    analogWrite(ledR, i);
    analogWrite(ledG, LOW);
    analogWrite(ledB, LOW);
    Serial.println(" ");
    Serial.print(programSelector);
    Serial.print(" Red Transition ");
    //    Serial.print(" i= ");
    //    Serial.print(i);
    xPosition = analogRead(xPin);
    if (xPosition >= 540)  {
      programSelector = programSelector - 1;
      i = 0;
      
      goto bailout;
    }
    if (xPosition <= 480) {     // bail out on sensor detect
      i = 0;
      programSelector = programSelector + 1;
      

      goto bailout;
    }
  }
bailout:
  Serial.println("works");
  Serial.println(programSelector);

  delay(1500);
}