Getting out_of_range error when running my code

Viewed 42

We have to write this code for class, but I am getting an out-of-range error from the part of code below. It is supposed to be like a simon-says thing, where the letter you have to type in is the same. The exact error I'm getting is:

terminate called after throwing an instance of 'std::out_of_range'
  what():  basic_string::at: __n (which is 1) >= this->size() (which is 1)
Abort (core dumped).
#include <iostream>                     // for I/O
#include <cstring>                      // for strlen()
#include <cstdlib>                      // for random numbers
#include <unistd.h>                     // for sleep()
using namespace std;

int main(int argc, char **argv) {

    const int DEFAULT_NUMBER_OF_ROUNDS = 15;
    int       numRounds = DEFAULT_NUMBER_OF_ROUNDS;

    // if a command line argument is given, use that string to init the
    // "random" sequence and set the number of rounds to play the game
    if (argc == 2) {
        numRounds = strlen(argv[1]);
    }

    string    s;                         // A string used to pause the game
    char     *seq = new char[numRounds]; // Sequence of numRounds colors to match
    char      colors[] = "RGBY";         // Allowable colors
    bool      lost = false;              // Indicates whether we win or lose
    int       round;                     // Indicates the current round

    // Initialize random number generator
    srand(time(0));

    // Determine the random color sequence using either argv[1] or
    // randomly determined letters from 'R', 'G', 'B', and 'Y'
    for (int j = 0; j < numRounds; j++) {
        seq[j] = (argc == 2) ? argv[1][j] : colors[rand() % 4];
    }

    // Wait until the player is ready
    cout << "Welcome to Simon, press enter to play .... ";
    getline(cin, s, '\n');


    //code
    string input;
    cout << flush;
    int I;
    round = 1;
    while(!lost){
        for(i = 0 ; i < round; i++){
            cout << "Simon says: " << seq[i] << flush;
            sleep(1);
            cout << "\010." << flush << endl;
        }

        cout << "Please enter " << round << " characters to match ";
        cin >> input;

        if (numRounds <= round){
            cout << "you won" << endl;
        }

        for(i = 0; i < round; i++);{
            if(input.at(i) != seq[i]){
                lost = true;
            }
        }

        cout << "you lost" << endl;
        cout << "the correct sequence was ";
        for(int i = 0; i < round; i++){
            cout << seq[I];
        }
        return 0;
    }
}
1 Answers

The error message is telling you that you have a std::string whose size() is 1 character, and you are trying to use its at() method to access a character at an index which is >= 1, which is out of bounds.

One problem I see is that this loop:

for(i = 0; i < round; i++);{
                          ^

Has an erroneous ; that causes the loop to do nothing but increment i until it reaches round, thus i is always equal to round in the subsequent expression if(input.at(i) != seq[i]). And at() performs bounds-checking, so will throw std::out_of_range if i >= input.size() is true.

After removing that erroneous semicolon, so the loop body is actually using i the way you intended, there is another problem. i is being used as an index into input and seq, however the lengths of input and seq are not guaranteed to be equal. Even though you are asking the user to enter round number of characters for input, you are not enforcing that.

The input.at(i) expression is the only expression in the whole program that is performing bounds-checking, and thus must be where the std::out_of_range error is being thrown from.

Also, you are never incrementing round. And, there is some logic in your while loop that should be moved after the loop has exited.

With that said, try something more like this:

#include <iostream>                     // for I/O
#include <cstring>                      // for strlen()
#include <cstdlib>                      // for random numbers
#include <limits>                       // for numeric_limits
#include <unistd.h>                     // for sleep()
using namespace std;

int main(int argc, char **argv) {

    const int DEFAULT_NUMBER_OF_ROUNDS = 15;
    int       numRounds = DEFAULT_NUMBER_OF_ROUNDS;

    // if a command line argument is given, use that string to init the
    // "random" sequence and set the number of rounds to play the game
    if (argc == 2) {
        numRounds = strlen(argv[1]);
    }

    string    seq(numRounds, '\0');      // Sequence of numRounds colors to match
    char      colors[] = "RGBY";         // Allowable colors
    bool      lost = false;              // Indicates whether we win or lose
    int       round = 1;                 // Indicates the current round

    // Initialize random number generator
    srand(time(0));

    // Determine the random color sequence using either argv[1] or
    // randomly determined letters from 'R', 'G', 'B', and 'Y'
    for (int j = 0; j < numRounds; ++j) {
        seq[j] = (argc == 2) ? argv[1][j] : colors[rand() % 4];
    }

    // Wait until the player is ready
    cout << "Welcome to Simon, press enter to play .... ";
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    //code
    string input;
    while (round <= numRounds){
        for(int i = 0; i < round; ++i){
            cout << "Simon says: " << seq[i] << flush;
            sleep(1);
            cout << "\b." << flush << endl;
        }

        do {
            cout << "Please enter " << round << " character(s) to match: ";
            cin >> input;
        }
        while (input.size() != round);

        for(int i = 0; i < round; ++i){
            if (input[i] != seq[i]){
                lost = true;
                break;
            }
        }

        /* alternatively:
        lost = (input.compare(0, round, seq, round) != 0);
        */

        if (lost)
            break;

        ++round;
    }

    if (lost){
        cout << "you lost" << endl;
        cout << "the correct sequence was ";
        for(int i = 0; i < round; ++i){
            cout << seq[i];
        }
        /* alternatively:
        cout.write(seq, round);
        */
    }
    else {
        cout << "you won" << endl;
    }

    return 0;
}
Related