-1

Here is my program, a star wars quiz game When I run the program, it gets to the cast[5] part, then crashes(segmentation fault)

#include<iostream>
#include<vector>
#include<string>
#include<fstream>

using namespace std;

class Character
{
  private:
    string first;
    string last;
    int episode;
  public:
    Character(string f, string l, int e);
    string getF();
    string getL();
    int getE();
};

  Character::Character(string f, string l, int e)
  :first(f),last(l),episode(e)
{
}

void readCast(vector<Character> &castFunc);


int main()
{
  int guess;
  int score = 0;
  vector<Character> cast;  
  cout<<"Welcome to the star wars quiz! I will tell you a character and you have to tell me what episode they first appeared in. Lets play!"<<endl;
  readCast(cast);  
  cout<<"What episode did "<<cast[0].getF()<<" "<<cast[0].getL()<<" first appear?"<<endl;
  cin>>guess;
  if(guess == cast[0].getE())
  {
    cout<<"Congratz! That is correct!"<<endl;
    score++;
  }
  else
  {
    cout<<"Sorry, that was not correct."<<endl;
  }
  cout<<"What episode did "<<cast[1].getF()<<" "<<cast[1].getL()<<" first appear?"<<endl;
  cin>>guess; 
  if(guess == cast[1].getE())
  {
    cout<<"Congratz! That is correct!"<<endl;
    score++;
  }
  else
  {
    cout<<"Sorry, that was not correct."<<endl;
  }
  cout<<"What episode did "<<cast[2].getF()<<" "<<cast[2].getL()<<" first appear?"<<endl;
  cin>>guess;
  if(guess == cast[2].getE())
  {
    cout<<"Congratz! That is correct!"<<endl;
    score++;
  }
  else
  {
    cout<<"Sorry, that was not correct."<<endl;
  }
  cout<<"What episode did "<<cast[3].getF()<<" "<<cast[3].getL()<<" first appear?"<<endl;
  cin>>guess;
  if(guess == cast[3].getE())
  {
    cout<<"Congratz! That is correct!"<<endl;
    score++;
  }
  else
  {
    cout<<"Sorry, that was not correct."<<endl;
  }
  cout<<"What episode did "<<cast[4].getF()<<" "<<cast[4].getL()<<" first appear?"<<endl;
  cin>>guess;
  if(guess == cast[4].getE())
  {
    cout<<"Congratz! That is correct!"<<endl;
    score++;
  }
  else
  {
    cout<<"Sorry, that was not correct."<<endl;
  }
 cout<<"What episode did "<<cast[5].getF()<<" "<<cast[5].getL()<<" first appear?"<<endl;
  cin>>guess;
  if(guess == cast[5].getE())
  {
    cout<<"Congratz! That is correct!"<<endl;
    score++;
  }
  else
  {
    cout<<"Sorry, that was not correct."<<endl;
  }
  cout<<"What episode did "<<cast[6].getF()<<" "<<cast[6].getL()<<" first appear?"<<endl;
  cin>>guess;
  if(guess == cast[6].getE())
  {
    cout<<"Congratz! That is correct!"<<endl;
    score++;
  }
  else
  {
    cout<<"Sorry, that was not correct."<<endl;
  }
  cout<<"Thanks for playing the Star Wars Quiz!"<<endl;
  cout<<"Your score was "<<score<<" out of 6!"<<endl;

  return 0;
}

void readCast(vector<Character> &castFunc)
{
  string first;
  string last;
  int episode;

  ifstream myFile;
  myFile.open("star_wars.txt");
  while(myFile.good())
  {
    myFile>>first;
    myFile>>last;
    myFile>>episode;

    Character list(first,last,episode);
    castFunc.push_back(list);
  }
}

string Character::getF()
{
  return first;
}

string Character::getL()
{
  return last;
}

int Character::getE()
{
  return episode;
}

This is the star_wars.txt file

Admiral Ackbar 6

Lando Calrissian 5

Padmé Amidala 1

Boba Fett 5

Jabba the Hutt 6

Obi-Wan Kenobi 4

Kylo Ren 7

Marcus Müller
  • 27,924
  • 4
  • 40
  • 79
Turtily
  • 11
  • 2
  • 5
    Run this in a debugger! Step through the code, watch variables. – abelenky Apr 15 '16 at 20:53
  • format your input file as code; this way, it's unclear whether there are blank lines between the lines wiht names, or not. – Marcus Müller Apr 15 '16 at 20:54
  • 3
    `Jabba the Hutt` that's a bunch of names, which one is `first` and which one is `last`? – n. 'pronouns' m. Apr 15 '16 at 20:56
  • `cast[0].getE()` `cast[1].getE()`, etc. etc. Why did you assume items 0, 1, etc. exist in the vector? Also, what if there were 1,000 names in your file? Write the same test 1,000 times, with the only difference being the index number??? I'm sure you can see the folly of writing code this way, and there has to be a much better alternative (like writing a loop) – PaulMcKenzie Apr 15 '16 at 20:57
  • 2
    Let me amplify that comment from @n.m. upon encountering that line, 'Jabba' is your first name, 'the' is your second name, you try to read `Hutt` as the `int` var `episode` and fail, the stream is now in fail-mode, thus not good so the while-loop breaks, and no more data is inserted beyond the last piece of data (jabba) which was incomplete and contains indeterminate content in `episode`, residing at element `[4]`. And that, kids, is why we **check IO operations and don't assume they succeeded**. – WhozCraig Apr 15 '16 at 20:59
  • Thanks for your help! – Turtily Apr 15 '16 at 21:10
  • 1
    @WhozCraig It is also worth remembering, just in case, that things we commonly believe about names are [all wrong](http://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/). – n. 'pronouns' m. Apr 15 '16 at 21:14
  • `while(myFile.good())` is almost as flawed as `while (! myFile.eof())`. It is testing if the stream is good before reading the stream, so who can say if `first`, `last`, or `episode` contain any worthwhile data at `Character list(first,last,episode);`. This helps hide your bug. Use `while(myFile>>first>>last>>episode)` instead. More here: http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong – user4581301 Apr 15 '16 at 21:46
  • I remember one poor gentleman whose last name was O. After years of being rejected by databases around the world--except for his local tax authority--he gave up and changed his name to Oh. – user4581301 Apr 15 '16 at 21:51

1 Answers1

1

because "Jabba the Hutt 6" is not composed by 2 strings and a number...

so:

while(myFile.good())
   {
     myFile>>first;
     myFile>>last;
     myFile>>episode;

     Character list(first,last,episode);
     castFunc.push_back(list);
   }

myFile>>episode gets a string, not a int episode;

DIEGO CARRASCAL
  • 1,918
  • 12
  • 16