0

I am having some problems in a program that I am trying to make in Visual Studio 2017. The Issue seems to be rooted in my use of the 'stoi()' function in the 'load_pokemon' function. I get the following error when I try to run the program:

Unhandled exception at 0x74A2A932 in ConsoleApplication1.exe: Microsoft C++ 
exception: std::invalid_argument at memory location 0x010EE918.

The function in question is here (it should be assumed that the Pokemon class is fully functional along with all of the member functions, as I believe that my usage of 'stoi' is the culprit):

void load_pokemon(Pokemon pokemon[]) {

    ifstream input_file;
    string file_name;
    int i = 0;
    string temp;
    int number;

    cout << "\n\nEnter Pokemon Data File Name: ";
    cin >> file_name;

    input_file.open(file_name.c_str());

    while (!input_file.eof()) {

        input_file >> temp;
        pokemon[i].assign_name(temp);
        temp.clear();

        input_file >> temp;
        pokemon[i].assign_type_1(temp);
        temp.clear();

        input_file >> temp;
        pokemon[i].assign_type_2(temp);
        temp.clear();

        input_file >> temp;
        number = stoi(temp);
        pokemon[i].assign_health_base(number);
        temp.clear();

        input_file >> temp;
        number = stoi(temp);
        pokemon[i].assign_health_multiplier(number);
        temp.clear();

        input_file >> temp;
        number = stoi(temp);
        pokemon[i].assign_attack_base(number);
        temp.clear();

        input_file >> temp;
        number = stoi(temp);
        pokemon[i].assign_attack_multiplier(number);
        temp.clear();

        input_file >> temp;
        number = stoi(temp);
        pokemon[i].assign_s_attack_base(number);
        temp.clear();

        input_file >> temp;
        number = stoi(temp);
        pokemon[i].assign_s_attack_multiplier(number);
        temp.clear();

        input_file >> temp;
        number = stoi(temp);
        pokemon[i].assign_defence_base(number);
        temp.clear();

        input_file >> temp;
        number = stoi(temp);
        pokemon[i].assign_defence_multiplier(number);
        temp.clear();

        input_file >> temp;
        number = stoi(temp);
        pokemon[i].assign_s_defence_base(number);
        temp.clear();

        input_file >> temp;
        number = stoi(temp);
        pokemon[i].assign_s_defence_multiplier(number);
        temp.clear();

        input_file >> temp;
        number = stoi(temp);
        pokemon[i].assign_speed_base(number);
        temp.clear();

        input_file >> temp;
        number = stoi(temp);
        pokemon[i].assign_speed_multiplier(number);
        temp.clear();

        input_file >> temp;
        pokemon[i].assign_move_1(temp);
        temp.clear();

        input_file >> temp;
        pokemon[i].assign_move_1_effect(temp);
        temp.clear();

        input_file >> temp;
        number = stoi(temp);
        pokemon[i].assign_move_1_max_pp(number);
        temp.clear();

        input_file >> temp;
        pokemon[i].assign_move_2(temp);
        temp.clear();

        input_file >> temp;
        pokemon[i].assign_move_2_effect(temp);
        temp.clear();

        input_file >> temp;
        number = stoi(temp);
        pokemon[i].assign_move_2_max_pp(number);
        temp.clear();

        input_file >> temp;
        pokemon[i].assign_move_3(temp);
        temp.clear();

        input_file >> temp;
        pokemon[i].assign_move_3_effect(temp);
        temp.clear();

        input_file >> temp;
        number = stoi(temp);
        pokemon[i].assign_move_3_max_pp(number);
        temp.clear();

        input_file >> temp;
        pokemon[i].assign_move_4(temp);
        temp.clear();

        input_file >> temp;
        pokemon[i].assign_move_4_effect(temp);
        temp.clear();

        input_file >> temp;
        number = stoi(temp);
        pokemon[i].assign_move_4_max_pp(number);
        temp.clear();

        i++;

    }

    return;

}

Test read in file:

Bulbasaur grass poison 3 2 4 2 5 3 4 2 5 3 3 2 Tackle physical 5 Vine_Whip 
physical 3 Synthesis heal 2 Poison_Powder poison 2

Ivysaur grass poison 4 2 5 2 6 3 5 2 6 3 4 2 Double-Edge physical 5 
Vine_Whip physical 3 Synthesis heal 2 Poison_Powder poison 2
  • See: http://en.cppreference.com/w/cpp/string/basic_string/stol#Exceptions – Fred Larson May 09 '17 at 20:04
  • 1
    Also see: http://stackoverflow.com/q/5605125/10077 – Fred Larson May 09 '17 at 20:05
  • why do you assume that a library function is at fault? – t0mm13b May 09 '17 at 20:07
  • I meant that my usage of stoi was the problem, that was worded badly. – Powerracer251 May 09 '17 at 20:09
  • So what is the value that you're passing to `std::stoi`? Everything else here is irrelevant to a question about `std::stoi`. – Lightness Races in Orbit May 09 '17 at 20:11
  • BTW, you can reduce your program size by eliminating the unnessary `temp.clear()` calls. A string will replace the old contents when used wih the `input_file >> temp`. – Thomas Matthews May 09 '17 at 20:11
  • 2
    _"it should be assumed that the Pokemon class is fully functional along with all of the member functions"_ No, it shouldn't. **Prove** it by removing them, presenting a [MCVE]. – Lightness Races in Orbit May 09 '17 at 20:11
  • You should be able to trim this down to about three lines if it is really `stoi` that is the problem (the bad input, the call and the result). I do actually think it is since `std::invalid_argument` is a valid exception for it to throw. – NathanOliver May 09 '17 at 20:13
  • @BoundaryImposition I would have, but that the class and implementation are over 1500 lines of code. I figured that would just be unwieldy to read. – Powerracer251 May 09 '17 at 20:15
  • 1
    You can use `input_file >> integer_value;` to read integer values. No need to read a string, then convert the string. – Thomas Matthews May 09 '17 at 20:15
  • BTW, the `stoi` will *throw an `std::invalid_argument` if no conversion could be performed.* -- [stoi reference](http://en.cppreference.com/w/cpp/string/basic_string/stol) – Thomas Matthews May 09 '17 at 20:18
  • I recommend you add `operator>>()` to your `Pokemon` class to read in the values. A lot more efficient than using an assignment function. Also, use `std::vector` and the `push_back()` method. – Thomas Matthews May 09 '17 at 20:24
  • @Powerracer251: You misunderstood, and/or didn't click on the link, and/or didn't read the page. You're not supposed to post 1500 lines of code. You're supposed to reduce the problem to a [MCVE]. In this case it'll probably be 3-4 lines long. – Lightness Races in Orbit May 09 '17 at 20:30
  • also you need to read up on how to read in a file properly because the code shown is not the proper way to read in a file at all. – Matthew May 09 '17 at 20:34
  • @Matthew In what way is what I did "improper"? Instead of making a claim like that maybe a tip would help. I did it as my textbook and class told me. – Powerracer251 May 09 '17 at 20:49
  • for instance the while loop should be `input_file.good()`. point of reference: http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong. also you can use `getline()` and something like `find()`. This way you do not have to waste the cpu on `clear()` calls. it is always a good practice to question any regardless of them being your prof or a textbook or even a forum. double check everyone because they could always be wrong or not have the best solution. – Matthew May 09 '17 at 20:57
  • also i try not to give tips unless your are doing something extremely wrong because it forces you to look up the problem and figure it out on your own and learn even more then any of us can teach you with a small code snippet. – Matthew May 09 '17 at 20:59

1 Answers1

1

The stoi function will throw an exception if no conversion could be performed.

I recommend you use a debugger and examine the contents of the string variable.

Also, you should add code to catch the exception and handle it.

You can always try code like this:

int health_modifier;
input_file >> health_modifier;
pokemon[i].assign_health_modifier(health_modifier);

The stream will not be in a good state if the read fails. So check the state of the input_file after reading (a good idea for all reads).

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154