Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ERROR: Label "foo" used but not defined

So I was fooling around with some C++ and got the previously stated error with some code that looked kind of like this:

#include <iostream>
using namespace std;

char foodstuffs;

void fruit()
{
cin>>foodstuffs;
switch(foodstuffs)
{
case 'a': goto foo; break;
case 'b': goto fooo; break;
}
}

int main()
{
cout<<"What do you want to eat? (a/b)";
fruit();
foo: cout<<"You eat an apple.";
fooo: cout<<"You eat a banana.";
}

The exact code was much more complex, but this is just to show you the error I got.

Now I realize that everyone despises the "goto" statement for some reason, but my actual code is full of so many gotos that I don't really have the time/patience to go back and change them all. Also, I'm kind of a novice programmer and I find gotos and labels to be very easy to use.

My question is how can I predefine these labels so that the function fruit() knows what they are? Also, I need to do this without moving the labels out of the main function.

like image 548
HurricaneFist Avatar asked Dec 16 '22 10:12

HurricaneFist


2 Answers

The goto statement can only go to locally defined labels, it can't jump to other functions.

So the labels in main will not be referenced, and the goto statements in fruit will not find the labels.

like image 134
Some programmer dude Avatar answered Jan 01 '23 23:01

Some programmer dude


What you are trying to do - jump between functions - is not valid for a whole slew of reasons, not least being object scope and life time, consider:

void foo()
{
    if(feelLikeIt)
       goto foobar;
}

void bar()
{
    std::string message = "Hello";
foobar:
    cout << message << endl;
}

Jumping to foobar from foo is illegal because "message" won't exist.

So the language just plain doesn't let you do this.

Further, the way you are trying to use "goto" would prevent you from re-using the "fruit()" function because it always makes a decision about what to do with the selection rather than the function calling it. What if you wanted to do this:

cout<<"What do you want to eat? (a/b)";
fruit();
foo: cout<<"You eat an apple.";
fooo: cout<<"You eat a banana.";
cout<<"What does your friend want to eat? (a/b)";
fruit();
// oops, you just created a loop because fruit made the decision on what to do next.

What you ACTUALLY want to do is use "fruit()" as a function that returns a value.

enum Fruit { NoSuchFruit, Apple, Banana };

Fruit fruit(const char* request)
{
    char foodstuffs;
    cout << request << " (a/b)";
    cin >> foodstuffs;
    switch (foodstuffs)
    {
        case 'a': return Apple;
        case 'b': return Banana;
        default:
            cout << "Don't recognize that fruit (" << foodstuffs << ")." << endl;
            return NoSuchFruit;
    }
}

const char* fruitNames[] = { "nothing", "an apple" ,"a banana" };

int main()
{
    Fruit eaten = fruit("What do you want to eat?");
    cout << "You ate " << fruitNames[eaten] << "." << endl;
    eaten = fruit("What does your friend want to eat?");
    cout << "Your friend ate " << fruitNames[eaten] << "." << endl;
}
like image 35
kfsone Avatar answered Jan 01 '23 21:01

kfsone