[Solved] (C++) Goto statement not working. Beginner [closed]


One of the most fundamental things we have to do as programmers is to learn to break problems into smaller problems. You are actually running into a whole series of problems.

I’m going to show you how to solve your problem. You may want to book mark this answer, because I’m pre-empting some problems you’re going to run into a few steps down the line and preparing you – if you pay attention – to solve them on your own 😉

Let’s start by stripping down your code.

Live demo here: http://ideone.com/aUCtmM

#include <iostream>

int main()
{
    std::cout << "Enter a number: ";
    int i;
    std::cin >> i;

    std::cout << "Enter a second number: ";
    int j;
    std::cin >> j;

    std::cout << "i = '" << i << "', j = '" << j << "'\n";
}

What are we checking here? We’re checking that we can ask the user two questions. That works fine.

Next is your use of goto, which I strongly recommend you do not use. It would be better to use a function. I’ll demonstrate with your goto case here first:

#include <iostream>

int main()
{
    int choice;
    std::cout << "Enter choice 1 or 2: ";
    std::cin >> choice;
    if ( choice == 1 )
        goto CHOSE1;
    else if ( choice == 2 )
        goto CHOSE2;
    else {
        std::cout << "It was a simple enough question!\n";
        goto END;
    }

CHOSE1:
    std::cout << "Chose 1\n";
    goto END;

CHOSE2:
    std::cout << "Chose 2\n";
    goto END;

END:
    std::cout << "Here we are at end\n";
}

live demo: http://ideone.com/1ElcV8

So goto isn’t the problem.

That leaves your use of variables. You’ve really mixed things up nastily by having a second set of variables (mm, uu). Not only do you not need to have these, you’re doing something very naughty in that these variables only exist inside one scope and not the other. You can “get away” with this but it will come back to haunt you later on.

The difference in your two main streams of code is the variable names. The second conversion case looks like this:

    MXNTUS:
int mm, uu;
cout << "Enter the amount of Pesos to Convert" << endl;
cout << "Amount: ";
cin >> mm;
uu = mm / 12.99;
cout << endl;
cout << "US Dollars: " << m << endl;
goto END;

The problem here is that you have – accidentally – used the variable “m” in your output. It’s what we call uninitialized.

cout << "US Dollars: " << m << endl;

That m in the middle should be mm.

Your compiler should actually be warning you about this. If it’s not, and you’re just setting out learning, you should figure out how to increase the compiler warning level.

It would be better to make a function to do the conversions; you could make one function for each direction, but I’ve made a function that handles both cases:

#include <iostream>

static const double US_TO_MXN = 12.99;
static const char DATA_DATE[] = "6/12/2014";

void convert(const char* from, const char* to, double exchange)
{
    std::cout << "Enter the number of " << from << " to convert to " << to << ".\n"
                 "Amount: ";
    int original;
    std::cin >> original;
    std::cout << to << ": " << (original * exchange) << '\n';
}

int main()  // this is valid since C++2003
{
    std::cout << "US/MXN Converter\n"
                 "1 US = " << US_TO_MXN << " MXN (" << DATA_DATE << ")\n"
                 "\n";

    int choice = 0;
    // Here's a better demonstration of goto
GET_CHOICE:
    std::cout << "Which conversion do you want to perform?\n"
                "[1] US to MXN\n"
                "[2] MXN to US\n"
                "Selection: ";
    std::cin >> choice;

    if (choice == 1)
        convert("US Dollars", "Pesos", US_TO_MXN);
    else if (choice == 2)
        convert("Pesos", "US Dollars", 1 / US_TO_MXN);
    else {
        std::cerr << "Invalid choice. Please try again.\n";
        goto GET_CHOICE;
    }

    // this also serves to demonstrate that goto is bad because
    // it's not obvious from the above that you have a loop.
}

ideone live demo: http://ideone.com/qwpRtQ

With this, we could go on to clean things up a whole bunch and extend it:

#include <iostream>
using std::cin;
using std::cout;

static const double USD_TO_MXN = 12.99;
static const double GBP_TO_MXN = 22.03;
static const char DATA_DATE[] = "6/12/2014";

void convert(const char* from, const char* to, double exchange)
{
    cout << "Enter the number of " << from << " to convert to " << to << ".\n"
                 "Amount: ";
    int original;
    cin >> original;
    cout << '\n' << original << ' ' << from << " gives " << int(original * exchange) << ' ' << to << ".\n";
}

int main()  // this is valid since C++2003
{
    cout << "Foreign Currency Converter\n"
            "1 USD = " << USD_TO_MXN << " MXN (" << DATA_DATE << ")\n"
            "1 GBP = " << GBP_TO_MXN << " MXN (" << DATA_DATE << ")\n"
            "\n";

    for ( ; ; ) {   // continuous loop
        cout << "Which conversion do you want to perform?\n"
                "[1] USD to MXN\n"
                "[2] MXN to USD\n"
                "[3] GBP to MXN\n"
                "[4] MXN to GBP\n"
                "[0] Quit\n"
                "Selection: ";
        int choice = -1;
        cin >> choice;
        cout << '\n';

        switch (choice) {
            case 0:
                return 0;       // return from main

            case 1:
                convert("US Dollars", "Pesos", USD_TO_MXN);
                break;

            case 2:
                convert("Pesos", "US Dollars", 1 / USD_TO_MXN);
                break;

            case 3:
                convert("British Pounds", "Pesos", GBP_TO_MXN);
                break;

            case 4:
                convert("Pesos", "British Pounds", 1 / GBP_TO_MXN);
                break;

            default:
                cout << "Invalid selection. Try again.\n";
        }
    }
}

http://ideone.com/iCXrpU

There is a lot more room for improvement with this, but I hope it helps you on your way.

—- EDIT —-

A late tip: It appears you’re using visual studio, based on the system("PAUSE"). Instead of having to add to your code, just use Debug -> Start Without Debugging or press Ctrl-F5. It’ll do the pause for you automatically 🙂

—- EDIT 2 —-

Some “how did you do that” points.

    cout << '\n' << original << ' ' << from << " gives " << int(original * exchange) << ' ' << to << ".\n";

I very carefully didn’t do the using namespace std;, when you start using more C++ that directive will become the bane of your existence. It’s best not to get used to it, and only let yourself start using it later on when you’re a lot more comfortable with C++ programming and more importantly debugging odd compile errors.

But by adding using std::cout and using std::cin I saved myself a lot of typing without creating a minefield of function/variable names that I have to avoid.,

What does the line do then:

    cout << '\n' << original << ' ' << from << " gives " << int(original * exchange) << ' ' << to << ".\n";

The ‘\n’ is a single character, a carriage return. It’s more efficient to do this than std::endl because std::endl has to go poke the output system and force a write; it’s not just the end-of-line character, it actually terminates the line, if you will.

int(original * exchange)

This is a C++ feature that confuses C programmers. I’m actually creating a “temporary” integer with the result of original * exchange as parameters.

int i = 0;
int i(0);

both are equivalent, and some programmers suggest it is better to get into the habit of using the second mechanism so that you understand what happens when you later run into something called the “most vexing parse” 🙂

convert("Pesos", "British Pounds", 1 / GBP_TO_MXN)

The 1 / x “invert”s the value.

    cout << "Foreign Currency Converter\n"
            "1 USD = " << USD_TO_MXN << " MXN (" << DATA_DATE << ")\n"
            "1 GBP = " << GBP_TO_MXN << " MXN (" << DATA_DATE << ")\n"
            "\n";

This is likely to be confusing. I’m mixing metaphors with this and I’m a little ashamed of it, but it reads nicely. Again, employ the concept of breaking problems up into smaller problems.

cout << "Hello " "world" << '\n';

(note: “\n” and ‘\n’ are different: “\n” is actually a string whereas ‘\n’ is literally just the carriage return character)

This would print

Hello world

When C++ sees two string literals separated by whitespace (or comments) like this, it concatenates them, so it actually passes “Hello world” to cout.

So you could rewrite this chunk of code as

    cout << "Foreign Currency Converter\n1 USD = ";
    cout << USD_TO_MXN;
    cout << " MXN (";
    cout << DATA_DATE;
    cout << ")\n1 GBP = ";
    cout << GBP_TO_MXN;
    cout << " MXN (";
    cout << DATA_DATE;
    cout << ")\n\n";

The << is what we call “semantic sugar”. When you write

cout << i;

the compiler is translating this into

cout.operator<<(i);

This odd-looking function call returns cout. So when you write

cout << i << j;

it’s actually translating it to

(cout.operator<<(i)).operator<<(j);

the expression in parenthesis (cout.operator<<(i)) returns cout, so it becomes

cout.operator<<(i); // get cout back to use on next line
cout.operator<<(j);

Main’s fingerprint

int main()
int main(int argc, const char* argv[])

Both are legal. The first is perfectly acceptable C or C++. The second is only useful when you plan to capture “command line arguments”.

Lastly, in main

return 0;

Remember that main is specified as returning int. The C and C++ standards make a special case for main that say its the only function where it’s not an error not to return anything, in which case the program’s “exit code” could be anything.

Usually its best to return something. In C and C++ “0” is considered “false” while anything else (anything that is not-zero) is “true”. So C and C++ programs have a convention of returning an error code of 0 (false, no error) to indicate the program was successful or exited without problems, or anything else to indicate (e.g. 1, 2 … 255) as an error.

Using a “return” from main will end the program.

3

solved (C++) Goto statement not working. Beginner [closed]