10 Replies - 362 Views - Last Post: 07 November 2018 - 08:31 PM Rate Topic: -----

#1 adamchalkley   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 38
  • Joined: 17-July 15

Must be an error with my compiler?

Posted 06 November 2018 - 05:37 PM

Hi guys,

So I have run into an bug that is making me want to pull my hair out,

I am making a simple hangman console game which I thought would be a walk in the park and it really should be but I am getting an out of range exception which is very strange because I know my bool array is 100% not out of range

Sorry about all the debugging couts, anyway I narrowed it down to the boolean array when I removed the letterChoosen[i] = true from my check value function everything runs smooth and fine,so baffled at this point I checked my constructor to see if I would get the same message if I set all of my bool in the array to true and yes it seems to give me an out of range exception when I change them to true instead of false.

this is fine

 for(int i = 0; i < wordLength; i++){

            cout << "worked" << endl;
            choosenLetter[i] = false;
        }


but this throws an std:: out of range exception

 for(int i = 0; i < wordLength; i++){

            cout << "worked" << endl;
            choosenLetter[i] = true;
        }







#include <iostream>
#include <stdlib.h>
#include <time.h>

using namespace std;

class Hangman{

private:
    string words[10];
    string wordName;
    int mistakes;
    int wordLength;

public:
    int random;
    bool* choosenLetter;
    char letter;

    Hangman(){

        //random = rand() % 9;
        random = 3;

        cout << random << endl;

        // make words
        words[0] = "Shallow Hall";
        words[1] = "Dodgeball";
        words[2] = "Nightmare on Elm Street";
        words[3] = "Forrest Gump";
        words[4] = "Halloween";
        words[5] = "Batman";
        words[6] = "Spider man";
        words[7] = "Anchorman";
        words[8] = "Meet the Parents";
        words[9] = "Oceans thirteen";

        wordName = words[random];
        wordLength = wordName.size();
        cout << "word length!!! " << wordLength << endl;
        choosenLetter = new bool[wordLength];

        for(int i = 0; i < wordLength; i++){

            cout << "worked" << endl;
            choosenLetter[i] = false;
        }

        mistakes = 0;
    }

    ~Hangman(){

      delete[] choosenLetter;

    }

    int getMistakes(){

        return mistakes;
    }

    string getWord()const{

       wordName;
    }

    bool checkValue(){

        cout << "word name " << wordName << endl;
        cout << "word " << wordLength << endl;
        cout << "letter " << letter << endl;

        for(int i = 0; i < wordLength; i++){

            if(letter == wordName.at(i) && !choosenLetter[i]){

                cout << "word name letter " << wordName.at(i) << endl;
                cout << i << endl;
                cout << "wordname size" << wordName.size() << endl;
                //choosenLetter[i] = true;
                return true;
            }
        }

       return false;
    }

    bool isWordComplete(){

       for(int i = 0; i < wordLength; i++){

         if(!choosenLetter[i]){

            return false;
         }
       }
       return true;
    }

    int& operator++(){

        mistakes++;
        return mistakes;
    }

    friend ostream& operator<<(ostream& os, const Hangman& h);
    friend istream& operator>>(istream& is, const Hangman& h);

};

ostream& operator<<(ostream& os,const Hangman& h){

  for(int i = 0; i < h.wordLength; i++){

    if(h.choosenLetter[i]){

        os << h.getWord().at(i);
    }
    else{

        os << '_';
    }
  }

  return os;
}

istream& operator>>(istream& is,Hangman& h){

   is >> h.letter;
   return is;
}


int main()
{
    srand(time(NULL));

    Hangman* hangman = new Hangman;

    bool gameOver = false;

    while(!gameOver){

        cout << *hangman;

        cout << endl;
        cout << "enter a letter" << endl;

        cin >> *hangman;


        if(!hangman->checkValue()){

             cout << "nooooow" << endl;
            ++*hangman;
        }

        // cout << "mistakes " << hangman->getMistakes() << endl;


//        if(hangman->getMistakes() == 18){
//            cout << "nooooow 2" << endl;
//            gameOver = true;
//        }
//        if(hangman->isWordComplete()){
//            cout << "nooooow 3" << endl;
//            //gameOver = true;
//        }
    }
    return 0;
}


here is the output

Quote

enter a letter
o
word name Forrest Gump
word 12
letter o
word name letter o
1
wordname size12
_terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::at: __n (which is 1) >= this->size() (which is 0)


any ideas what may be going on,I am starting to think it's a bug in my compiler I am using a mingw 32 bit compiler with the codeblocks IDE for windows.

Is This A Good Question/Topic? 0
  • +

Replies To: Must be an error with my compiler?

#2 BetaWar   User is offline

  • #include "soul.h"
  • member icon

Reputation: 1561
  • View blog
  • Posts: 8,352
  • Joined: 07-September 06

Re: Must be an error with my compiler?

Posted 06 November 2018 - 06:30 PM

Yes, that appears to be either a compiler issue, or that something is being inappropriately cached between compiles and has been resolved but not recompiled. Either way, with g++ 8.2.1, I do not see the issue you are seeing.

One thing you may want to consider, if it is an option, would be to run a Linux VM and use it for the development work; as you can typically get newer versions of development tools that way (and for free in many cases). It isn't Windows, but I found that I made the jump to Linux as my primary OS about a year ago and am enjoying it.
Was This Post Helpful? 0
  • +
  • -

#3 snoopy11   User is offline

  • Engineering ● Software
  • member icon

Reputation: 1550
  • View blog
  • Posts: 4,930
  • Joined: 20-March 10

Re: Must be an error with my compiler?

Posted 06 November 2018 - 07:53 PM

Well I won't pretend to know how you play Hangman but I usually draw a wee guy hanging from the gallows.

Anywhoo

this

string getWord()const
    {

       wordName;
    }




has a string as its return type so should probably return something.. ie a string.

and what you new you must delete

this

Hangman* hangman = new Hangman;


but is it really necessary to make a pointer here?, where is the advantage of it....? does it make sense ... is it a good design choice? etc.
Was This Post Helpful? 1
  • +
  • -

#4 Salem_c   User is offline

  • void main'ers are DOOMED
  • member icon

Reputation: 2238
  • View blog
  • Posts: 4,325
  • Joined: 30-May 10

Re: Must be an error with my compiler?

Posted 06 November 2018 - 09:42 PM

Just to follow up snoopy11, turn up your compiler warnings as much as possible.
$ g++ -Wall -Wextra foo.cpp
foo.cpp: In member function ‘std::__cxx11::string Hangman::getWord() const’:
foo.cpp:66:8: warning: statement has no effect [-Wunused-value]
        wordName;
        ^
foo.cpp:67:5: warning: no return statement in function returning non-void [-Wreturn-type]
     }
     ^



Your exception is an out of range on a string, and you have an issue in the compiled code relating to returning a string.
Was This Post Helpful? 1
  • +
  • -

#5 sepp2k   User is offline

  • D.I.C Lover
  • member icon

Reputation: 2662
  • View blog
  • Posts: 4,256
  • Joined: 21-June 11

Re: Must be an error with my compiler?

Posted 07 November 2018 - 08:53 AM

The [] operator does not throw std::out_of_range, the at method does, so you're wrong about where the exception is being thrown. Generally you should use the debugger to find out where an exception is being thrown (and what the values of the variables are when it is), but in this case it's clearly h.getWord().at(i);.

The other posters have already pointed out what the problem is there.

View PostBetaWar, on 07 November 2018 - 02:30 AM, said:

Either way, with g++ 8.2.1, I do not see the issue you are seeing.


That's due to the wonders of undefined behaviour, not compilation issues.
Was This Post Helpful? 1
  • +
  • -

#6 adamchalkley   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 38
  • Joined: 17-July 15

Re: Must be an error with my compiler?

Posted 07 November 2018 - 09:17 AM

It's strange though that when I commented out the code that set the bools to true the code worked fine, I wonder why??

anyway I decided to make wordName a public instead of private variable and removed the getWord() function that was const and used the variable instead,

and this seems to work anybody know why by just changing getWord().at(i) with wordName.at(i) made such a drastic difference and stopped giving me the exception?

thanks

#include <iostream>
#include <stdlib.h>
#include <time.h>

using namespace std;

class Hangman{

private:
    string words[10];
    int mistakes;

public:
    int random;
    bool* choosenLetter;
    char letter;
    int wordLength;
    string wordName;

    Hangman(){

        random = rand() % 9;
        //random = 3;

        // cout << random << endl;

        // make words
        words[0] = "Shallow Hall";
        words[1] = "Dodgeball";
        words[2] = "Nightmare on Elm Street";
        words[3] = "Forrest Gump";
        words[4] = "Halloween";
        words[5] = "Batman";
        words[6] = "Spider man";
        words[7] = "Anchorman";
        words[8] = "Meet the Parents";
        words[9] = "Oceans thirteen";

        wordName = words[random];
        wordLength = wordName.size();
        cout << "word length!!! " << wordLength << endl;
        choosenLetter = new bool[wordLength];

        for(int i = 0; i < wordLength; i++){

            //cout << "worked" << endl;
            choosenLetter[i] = false;
        }

        mistakes = 0;
    }

    ~Hangman(){

      delete[] choosenLetter;

    }

    int getMistakes(){

        return mistakes;
    }

    bool checkValue(){

        bool found = false;

        for(int i = 0; i < wordLength; i++){

            if(letter == wordName.at(i) && !choosenLetter[i]){

                choosenLetter[i] = true;
                found = true;
            }
        }
       if(found){

          return true;
       }else{

       return false;
       }
    }

    void findGap(){

       for(int i = 0; i < wordLength; i++){
       if(wordName.at(i) == ' ' && !choosenLetter[i]){

            choosenLetter[i] = true;
         }
       }
    }

    
    bool isWordComplete(){

       for(int i = 0; i < wordLength; i++){

         if(!choosenLetter[i]){

            return false;
         }
       }
       return true;
    }

    int& operator++(){

        mistakes++;
        return mistakes;
    }

    friend ostream& operator<<(ostream& os, const Hangman& h);
    friend istream& operator>>(istream& is, const Hangman& h);

};

ostream& operator<<(ostream& os,const Hangman& h){

  cout << endl;
  cout << endl;
  for(int i = 0; i < h.wordLength; i++){

    if(h.choosenLetter[i]){

        os << h.wordName.at(i);
    }
    else{

        os << '_';
    }
  }
  cout << endl;
  cout << endl;
  return os;
}

istream& operator>>(istream& is,Hangman& h){

   is >> h.letter;
   return is;
}


int main()
{
    srand(time(NULL));

    Hangman* hangman = new Hangman;

    bool gameOver = false;

    while(!gameOver){

        system("cls");

        hangman->findGap();
        //hangman->draw();  implement later

        cout << *hangman;

        cout << endl;
        cout << "enter a letter" << endl;

        cin >> *hangman;


        if(!hangman->checkValue()){

            ++*hangman;
        }

        if(hangman->getMistakes() == 6){
            system("cls");
            // hangman->draw(); implement later
            cout << "GAME OVER! YOU LOSE" << endl;
            gameOver = true;
        }

        if(hangman->isWordComplete()){
            cout << "GAME OVER! YOU WIN!!!" << endl;
            gameOver = true;
        }
    }
    return 0;
}



Was This Post Helpful? 0
  • +
  • -

#7 adamchalkley   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 38
  • Joined: 17-July 15

Re: Must be an error with my compiler?

Posted 07 November 2018 - 09:23 AM

string getWord()const{
 
       wordName;
    }




So this was my error all along?
Was This Post Helpful? 0
  • +
  • -

#8 snoopy11   User is offline

  • Engineering ● Software
  • member icon

Reputation: 1550
  • View blog
  • Posts: 4,930
  • Joined: 20-March 10

Re: Must be an error with my compiler?

Posted 07 November 2018 - 11:51 AM

Yes, that was your error.

But you have many design considerations to make IMO.
Was This Post Helpful? 0
  • +
  • -

#9 adamchalkley   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 38
  • Joined: 17-July 15

Re: Must be an error with my compiler?

Posted 07 November 2018 - 01:25 PM

thanks Snoopy,

what should I look at improving in my design?

constructive criticism always appreciated :)/> I'm trying to improve every day

This post has been edited by Skydiver: 07 November 2018 - 02:22 PM
Reason for edit:: Remove unnecessary quote. No need to quote the post above yours.

Was This Post Helpful? 0
  • +
  • -

#10 #define   User is offline

  • Duke of Err
  • member icon

Reputation: 1855
  • View blog
  • Posts: 6,678
  • Joined: 19-February 09

Re: Must be an error with my compiler?

Posted 07 November 2018 - 04:22 PM

You could include the string header

#include <string>


I know that iostream includes it but including it documents that you are using it.

In C++ the other includes from the C runtime library are

#include <cstdlib>
#include <ctime>



The Hangman class is looking large so I would try reducing the size, if permitted.

Options to tackle this could be :

1) Moving the word/phrase list to global space or another class. The data is constant so making a const string array that is initialized with the data is elementary. Or a class could be created that contains the data, perhaps using a vector, and a function that returns a random word/phrase string. Another function could return a specified string as you have now.

2) Moving large function definitions outside of the class. For that, the compiler needs to be told that the functions are part of the class - with the class name and scope resolution operator e.g. Hangman::

3) Moving the data concerning the word/phrase to guess, to a separate class. The class would have functions to return the word/phrase, return the word/phrase length, return the number of mistakes, check a chosen letter, return a masked word/phrase, and to initialize/reset the data. Most of that functionality you've already attempted.
Was This Post Helpful? 1
  • +
  • -

#11 snoopy11   User is offline

  • Engineering ● Software
  • member icon

Reputation: 1550
  • View blog
  • Posts: 4,930
  • Joined: 20-March 10

Re: Must be an error with my compiler?

Posted 07 November 2018 - 08:31 PM

I would also add making hangman a pointer to Hangman is unnecessary simply instantiate the object thus

Hangman hangman;



and use the . operator instead of the -> operator.

Your entire game loop could be constructed as so

bool ifWon = false;
while(hangman.checkGuesses())
    {

        cout << "Word is a film with "<< hangman.getWordLength() <<" Letters." << endl;
        hangman.displayWord();

        string input;
        cout << "Enter a letter to guess? ";
        cin >> input;
        hangman.getGuess(input);
        if (hangman.gameWon == true)
        {
            hangman.displayWord();
            cout << "You Won !!";
            ifWon = true;
            break;
        }
    }
    if(!ifWon)
        cout << "You Lost, the Film was "<< hangman.displayWord() << endl;


then consider adding a Drawing class to Draw the hangman on the Gallows, once you have the above down.

 ╔══╗
 ○  ║
╱│╲ ║
╱ ╲ ║
    ║
    ║



the drawing should consist of 6 stages from the empty gallows to the head(1), to the body(1), to the arms(2) and finally the legs(2).

For the actual Hangman class, you only need 4 class functions plus a constructor and a destructor.

those four functions would be

bool checkGuesses
bool getGuess
bool displayWord
int getWordLength 


It's a simple game your solution should also be simple and not complex, sometimes you can overthink something but self-awareness should tell you something is wrong.

Also when writing C++ code try not to fall into the trap of writing it in a C style, C++ has very different paradigms to C. Your code should use as many C++ features as possible and none to little C features unless there is a specific need for that C feature.

This post has been edited by snoopy11: 07 November 2018 - 08:33 PM

Was This Post Helpful? 2
  • +
  • -

Page 1 of 1