-2

Recently I have been making a text-based game to imitate a game from the 90's for my friend, and it went all well, but the Yes/No didn't work because I had an if statement then another if statement following first, so then I change it to an if statement with an else statement following the if statement, but get error's like "else without previous if" and "label referenced but not defined" which is really weird because a few lines below the reference in the defined label... I really need help with this, because I tried googling it but comes up with useless Microsoft threads that don't relate whatsoever.

My Code:

#include <iostream>

int main() //main function
{
    std::cout << "NOTE: when you see [Y/N], it is a choice option, please capitalize letter of choice!!\n";
    lab1:
    char name = NULL;
    int age = NULL;
    char ans1 = NULL;
    char strong = NULL;
    char ans2 = NULL;
    char ans3 = NULL;
    char smart = NULL;
    char ans4 = NULL;
    char ans5 = NULL;

    std::cout << "Well hello! What is your name?\n";
    std::cin >> name;
    std::cout << "And your age is?\n";
    std::cin >> age;

    std::cout << "Ok so your name is " << name << " and you are " << age << "?\n";
    std::cout << "Is that correct? [Y/N]\n";
    std::cin >> ans1;
    if (ans1 == 'Y');
    {
        std::cout << "Well then, lets get started with your main ability!\n";
        goto lab2;
    }
    else
    {
        std::cout << "Oh sorry, my bad lets enter it again shall we?\n";
        goto lab1;
    }
    lab2:
    lab4:
    lab6:
    std::cout << "Strong? [Y/N]\n";
    std::cin >> strong;
    if (strong == 'Y');
    {
        std::cout << "Are you sure? Only ONE main ability can be chosen! [Y/N]\n";
        std::cin >> ans2;
        if (ans2 == 'Y')
        {
            goto lab3;
        }
        else
        {
            goto lab4;
        }
    }
    else
    {
        std::cout << "Are you sure? Move to next ability? [Y/N]\n";
        std::cin >> ans3;
        if (ans3 == 'Y');
        {
            goto lab5;
        }
        else
        {
            goto lab6;
        }
        

    }
    lab5:
    lab8:
    lab10:
    std::cout << "Smart? [Y/N]\n";
    std::cin >> smart;
    if (smart == 'Y')
    {
        std::cout << "Are you sure? Only ONE main ability can be chosen! [Y/N]\n";
        std::cin >> ans4;
        if (ans4 == 'Y')
        {
            goto lab7;
        }
        else
        {
            goto lab8;
        }

    }
    else
    {
        std::cout << "Are you sure? Move to next ability? [Y/N]\n";
        std::cin >> ans5;
        if (ans5 == 'Y')
        {
            goto lab9;
        }
        else
        {
            goto lab10;
        }
    }
    lab9:
    lab3:
    lab7:
    std::cout << "Done!";
    

    

}
Irelia
  • 3,407
  • 2
  • 10
  • 31
  • 4
    This is the definition of spaghetti code and when using labels can go wrong – Irelia Jan 25 '22 at 00:41
  • 5
    Remove the semicolons at the end of the `if` statements that have them. Like this one `if (ans3 == 'Y');` – Retired Ninja Jan 25 '22 at 00:42
  • 1
    When you find yourself making sequentially named or numbered variables consider using an array instead. Very often it will simplify the code. – user4581301 Jan 25 '22 at 00:45
  • 2
    Side note: Don't comment the obvious stuff. If the reader can't figure out that `int main() //main function` is the `main` function without the comment, there's not much you can do to help them other than offer them [a good book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). Where you think you need a comment, first see if more-descriptive identifiers on the variables and functions involved help. – user4581301 Jan 25 '22 at 00:49
  • Side note: in `char name = NULL;` `NULL` is a pointer, not a `char`, so assigning `NULL` to `name` obscures the intent or perhaps it reinforces the fact that something called `name` should not be a `char`, a single character, and should instead be a `std::string` a collection of characters. – user4581301 Jan 25 '22 at 00:52
  • BTW, a `char` holds 1 (one) letter. You are asking the User for a one letter name. If you want more than 1 letter, use `std::string`. – Thomas Matthews Jan 25 '22 at 01:08
  • Also, `int` is looking for numbers, not NULL. Initialize your `int` variable to a number like 0. – Thomas Matthews Jan 25 '22 at 01:09
  • 1
    Search the internet for "c++ spaghetti code goto". – Thomas Matthews Jan 25 '22 at 01:10
  • Try writing your code without `goto` and labels. Use `while`, `switch`, `for` and `do-while`. These structure elements will help you avoid compiler errors dealing with labels. – Thomas Matthews Jan 25 '22 at 01:12
  • @ThomasMatthews Top link for me: https://stackoverflow.com/questions/67537675/how-to-input-a-character-into-an-int-without-breaking-the-console-and-giving-an – user4581301 Jan 25 '22 at 01:15
  • 1
    The code is spaghetti (i.e horrible) but the actual question is because of how `if` statements work. In `if (ans1 == 'Y'); { // stuff } else` the `;` ends one empty statement and the `{}` forms a block statement. So there are two statements between the `if` and the `else` that you intend to associate with it. That is wrong - ONLY ONE statement between the `if` and the corresponding `if` is allowed (if more than one was allowed, things would be ambiguous with nested `if` statements). The solution in your case is to remove the `;` – Peter Jan 25 '22 at 01:48

1 Answers1

3

I know this doesnt answer your question but I am going to give advice.

Code like this with that many labels is very fragile (meaning its hard to change as your project grows). I have worked on large c++ projects (100,000 lines +) and every goto and label had to be individually justified. Many probably had none. You should develop a dislike of typing the characters 'g' 'o' 't' 'o'.

So how do you do what you code is trying to do. The common idiom is

std::string ans;

while(true)
{
    std::cout >> "Are you sure";
    std::cin >> ans;
    if(ans == "Y" || ans == "N")
      break;
    
}

if (ans == "Y")
{
  //do the yes thing
}
else
{
  // do the no thing
}

This will keep looping , asking the user a Yes No question until they answer Y or N

Taking your example of Smart

bool isSmart = false;
while(true)
{
   std::cout << "Smart? [Y/N]\n";
   std::cin >> smart;
   if (smart == 'Y')
   {
      std::cout << "Are you sure? Only ONE main ability can be chosen! ";
    std::cin >> ans4;
    if (ans4 == 'Y')
    {
       isSmart = true;
        break;
    }
  }
}

EDIT, answer the original question

You have

  if (ans3 == 'Y');
    {
        goto lab5;
    }
    else
    {
        goto lab6;
    }

this is invalid syntax

you need

  if (ans3 == 'Y') // <=== no ;
    {
        goto lab5;
    }
    else
    {
        goto lab6;
    }

You have this same error in multiple places

pm100
  • 48,078
  • 23
  • 82
  • 145
  • 1
    Addendum: Sometimes you'll find yourself with nested loops that you cannot easily `break` out of. Before reaching for `goto`, see if you can move the loops into a function that you can `return` from. – user4581301 Jan 25 '22 at 01:06
  • 1
    Fun with `bool`: `isSmart = (ans4 == 'Y') || (ans4 == 'y');` You can eliminate a lot of `if` statements by using `bool` assignments. :-) – Thomas Matthews Jan 25 '22 at 01:18
  • I too dislike the use of goto; however I find it justifiable to use when jumping to a location to clean all resources in case of failure. Similar to a `do{ }while(0);` and breaking when an error occurs – Irelia Jan 25 '22 at 01:40
  • I don't disagree with your advice about avoiding spaghetti code, but up-votes for an answer that doesn't even attempt to address the question asked leaves a bit of a stench. For example, you could explain why a semi-colon in `if (ans == 'Y'); {} else {}` triggers the error messages that were asked about. – Peter Jan 25 '22 at 01:55
  • @Peter i just assumed that the comments of others would have answered that. I will edit the answer – pm100 Jan 25 '22 at 05:50
  • @Yuumi of course goto is justified in many cases. Otherwise we end up with very convoluted logic with multiple nested loops. For a novice the advice stands tho – pm100 Jan 25 '22 at 05:54