-1

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;
    }
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Which line do you get out of range? Maybe you want to make sure that the user entered the proper number of characters? `if(input.at(i) != seq[i]){` would throw this error if i was greater than or equal to `input.length()` and that would happen if the user entered less than round characters. – drescherjm Sep 23 '22 at 19:02
  • 1
    `int I;` at the top does't initialize `I`. When that value is used later, in `cout << seq[I]`, it still hasn't been assigned a value. So the result is nonsense. – Pete Becker Sep 23 '22 at 19:03
  • And it this case, that nonsense result appears to be a kinder-than-average tool chain reporting an out of range error. – user4581301 Sep 23 '22 at 19:08
  • Welcome to Stack Overflow. "I am getting an out-of-range error" Well, did you try to figure out what indexes are being attempted? Did you try to figure out what indexes are valid? Please read https://ericlippert.com/2014/03/05/how-to-debug-small-programs/ and [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/questions/25385173/). The problem that was pointed out here is a simple typo, which makes the question off topic for Stack Overflow. You are expected to try to look for these things before posting. – Karl Knechtel Sep 23 '22 at 23:36

1 Answers1

1

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;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770