Getting out_of_range error when running my code - c++

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;
}
}

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

How to stop the program when the user inputs a char or string in an int variable?

So i have this homework to do where the user inputs a number and how many number he wants to check and the computer tells him the numbers for which the first number is divisible.
The thing is that I wanted to do a little extra on the homework to block the program once a char or string is inputted, because else the program would crash
#include <iostream>
#include <stdlib.h>
#include <vector>
using namespace std;
int main() {
unsigned int myNum, nTimes;
bool Continue = true;
char ContinueYN;
vector<int> nDiv;
while (Continue) {
cout << "Insert a number.";
cin >> myNum;
cout << "How many numbers do you want to check?";
cin >> nTimes;
for (int I = 1; nTimes >= I; I++) {
if (myNum % I == 0) {
nDiv.push_back(I);
}
}
cout << "The number is divisible for the following numbers: ";
for (int i = 0; i < nDiv.size(); ++i) {
cout << nDiv[i] << ' ';
}
cout << "\nPress any letter to continue or press n to stop\n";
cin >> ContinueYN;
ContinueYN = tolower(ContinueYN);
if (ContinueYN == 'n') {
Continue = false;
}
nDiv.clear();
system("cls");
}
return 0;
}

while loop turning into an infinite loop for non bool values [duplicate]

I'm trying to build the Bulls & Cows game in C++. I've implemented most of the logic. The game runs continuously with the use of an infinite loop and generates a random value at each run.
What I'm trying to do now is to now is to take the user input and run the code if the input is valid (can ONLY be a 4 digit integer). This is my implementation:
#include ...
using namespace std;
vector<int> getDigits(int modelValue) {
vector<int> vectorValue;
int extractedDigit = 0;
int modulant = 10000;
int divisor = 1000;
for (int i = 0; i < 4; i++) {
extractedDigit = (modelValue % modulant) / divisor;
vectorValue.push_back(extractedDigit);
modulant /= 10;
divisor /= 10;
}return vectorValue;
}
int main() {
for (;;) {
int model = rand() % 9000 + 1000;
int guess = 0000;
int bulls = 0;
int cows = 0;
int counter = 1;
cout << "This is the random 4-digit integer: " << model << endl;
cout << "Enter a value to guess: ";
cin >> guess;
if ((guess >= 1000) && (guess <= 9999) && (cin)) {
vector<int> modelVector = getDigits(model);
vector<int> guessVector = getDigits(guess);
for (int i = 0; i < 4; i++) {
if (find(modelVector.begin(), modelVector.end(), guessVector[i]) != modelVector.end()) {
if (modelVector[i] == guessVector[i]) { bulls += 1; }
else { cows += 1; }
}
}cout << "There are " << bulls << " bulls and " << cows << " cows" << endl;
}
else {
cout << "Please enter a valid 4-digit integer between 0000 and 9999" << endl;
cin.clear();
}
}return 0;
}
But when I run and input something invalid, what I get is a continuously running .
There's nothing wrong with the way you read the user input, it just doesn't check for the input type before assigning the value into your 'guess' variable.
So, if an user put any value that isn't accepted by the integer type it would crash your application generating this infinite loop.
To protect your integer variable from wrong user inputs you must replace your direct input assignment:
cin >> guess;
By a protected one:
while(!(cin >> guess) || (guess < 1000)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input. Please, try again: ";
}
Into the while above you can see the "numeric_limits::max()" which is explained here:
Returns the maximum finite value representable by the numeric type T. Meaningful for all bounded types.
At the end you have a while holding the user into this reading loop while its input is under 1000 (as requested) or isn't a valid integer.
Try out cin.ignore(). It'll help you flush the cin buffer.

ask the user if a sequence of two letters is in a random array of letters

The user inputs some desired length of a string of characters . then the program outputs a list of randomly generated characters. After which the user is prompted to input 2 characters (that either exist or does not exist whiten the list). the program will then output where the first character appears in the pair or say that the pair does not exist in the list.
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
int main()
{
int size, c;
char ltr1, ltr2;
cout << "How many letters do you want in your random sting? ";
cin >> size;
string str;
for (int i = 0; i < size; i++)
{
c = rand() % 26 + 'a';
str.push_back(c);
}
for (int i = 0; i < size; i++)
{
cout << str[i];
}
cout << endl << endl;
cout << "what pair of letters would you like to find?";
cin >> ltr1;
cin >> ltr2;
cout << endl;
for (int i = 0; i < size; i++)
{
if (char((str[i] == ltr1) && (str[i + 1] == ltr2)))
{
cout << "the pair is in the string starting at character number "
<< i << " in the string" << endl;
}
if (char((str[i] == ltr1) && (str[i + 1] != ltr2)))
{
cout << "the pair " << ltr1 << ltr2 << " is not in the string." << endl;
}
}
return 0;
}
the output is capable of determining weather or not the pair exist or not and will output the location however if you input a value greater than 25 it will run the final output multiple times.

write program to display odd and even numbers

im trying to write this code but i couldn't
the q is :
by using for loop, write a program to receive input for any 5 numbers and display the total of even an odd numbers. the output should be as shown below
---------------------------------
Enter any 5 numbers: 0 1 3 2 11
0 is not even number.
total exists even = 1
total exist odd = 3
--------------------------------
and this is what i did:
#include<iostream>
using namespace std;
int main()
{
int i,j=0,c=0;
for(i=0;i<5;i++)
{
cout<<"enter 5 numbers "<<i ;
cin>>i;
}
if(i==0)
{
cout<< "0 is not even number"<<endl;
}
else if(i%2==0)
{j++;}
else if(i%2 !=0)
{c++;}
cout<<"total exists even : "<<j<<endl;
cout<<"total exists ODD : "<<c<<endl;
return 0;
}
Going through your code step by step (notice the changed formatting!):
#include<iostream>
using namespace std; // usually considered bad practice
int main()
{
int i, j=0, c=0;
for(i = 0; i < 5; i++)
{
cout << "enter 5 numbers " << i;
cin >> i; // you are overwriting your loop variable!!!
// how do you think your program will go on if you enter
// e. g. 7 right in the first loop run?
// additionally, you did not check the stream state afterwards
// if user entered something invalid (e. g. S), cin sets the
// fail flag and stops further reading - attemps doing so yield
// 0 (since C++11) or don't modify the variable (before C++11)
}
// this section is outside the loop already!
// so you are only checking the number you read in your loop in the very last run
if(i == 0)
{
cout << "0 is not even number" << endl;
}
else if(i % 2 == 0)
{
j++;
}
// this check is redundant: it is the complement to your previous
// check, so if the first went wrong, the second cannot be false any more
// (compare: you did not check for i != 0 either before doing the modulo check)
else /* if(i % 2 != 0) */
{
c++;
}
cout << "total exists even: " << j << endl;
cout << "total exists odd: " << c << endl;
return 0;
}
Changed code:
#include<iostream>
int main()
{
// several serious coding guide lines mandate: only one variable per line:
unsigned int odd = 0;
unsigned int even = 0;
// I used unsigned int here, negative counts are just meaningless...
// I'm consequent in these matters, but range of (signed) int suffices anyway,
// so you can use either one...
// C++ is not C (prior to C99) - keep scope of variables as local as possible
// (loop counter declared within for header, local variable within body)
for(unsigned int i = 0; i < 5u; i++) // (unsigned? see above)
{
std::cout << "enter 5 numbers (" << i << "): ";
int n; // separate variable!
if(!(std::cin >> n))
{
// some appropriate error handling!!! e. g.:
std::cout << "invalid value entered";
return -1;
}
// this now resides INSIDE the for loop
if(n == 0)
{
cout << "0 is not even number" << endl;
}
else
{
// this is an ALTERNATIVE calculation
n %= 2; // gets either 0 or 1...
odd += n;
even += 1 - n;
// (I personally prefer avoiding conditional branches but you *can*,
// of course, stay with the if/else you had before, too...
// - just don't check the complement as shown above)
}
}
cout << "total exists even: " << even << endl;
cout << "total exists odd: " << odd << endl;
return 0;
}
About the unsigned: Sometimes these are of advantage:
void f(int n) { /* need to check for both 0 <= n && n <= max! */ }
void f(unsigned int n) { /* n <= max suffices */ }
but sometimes one has to handle them with care:
for(unsigned int n = 7; n >= 0; --n) { /* ... */ } // endless loop!!!
for(unsigned int n = 7; n-- >= 0;) { /* ... */ } // correct variant
(the first one would have worked with signed int, but it is not the fault of the unsigned type, but the programmer's fault who did not chose the right type for what he or she intended...).
Just for completeness: Assuming we could drop the mathically incorrect statement that zero wasn't even, we could have it even much simpler:
unsigned int constexpr LoopRuns = 5u;
int main()
{
unsigned int odd = 0; // just one single variable...
for(unsigned int i = 0; i < LoopRuns; i++)
{
std::cout << "enter 5 numbers (" << i << "): ";
int n;
if(!(std::cin >> n))
{ /* ... */ }
odd += n %= 2;
}
// one single difference instead of five additions...
cout << "total exists even: " << LoopRuns - odd << endl;
cout << "total exists odd: " << odd << endl;
return 0;
}
This program will help you out.
#include <iostream>
int main () {
int num[5], even = 0, odd = 0;
bool hasZero = false;
std::cout << "Enter 5 numbers:"
for (int i = 0; i < 5; i++) {
std::cin >> num[i];
}
for (int i = 0; i < 5; i++) {
if (num[i] == 0) { // Checking if the current number is zero
hasZero = true;
} else if (num[i] % 2 == 0 ) { // Checking if the current number is even
++even;
} else { // If the number is not even, then it must be odd
++odd;
}
}
if (hasZero) { // If the input has zero then print following statement
std::cout << "0 is not an even number" << std::endl;
}
std::cout << "Total even count: " << even << std::endl;
std::cout << "Total odd count: " << odd << std::endl;
return 0;
}
If you are unable to understand any line, then you're most welcome in the comments section below ;)
The problem with your code:
In the for statement, you're using the same variable for both counter and input , i.e., i. This will allow neither for loop to execute properly nor the input to be captured properly.
You're overwriting the i variable everytime you take any input, then only the last input (out of 5 inputs) will be stored in memory.
You're just checking the last input, by using if statement, because the loop is already ended before.
If you want your code to run properly, then these modifications will make that work:
#include<iostream>
using namespace std;
int main()
{
int num,j=0,c=0; // Change the name to num here, because i will be used later as a counter variable.
for(int i=0;i<5;i++)
{
cout<<"enter 5 numbers "<<i ;
cin>>num;
// Don't end for loop here, this will not allow every input to be checked.
if(num==0)
{
cout<< "0 is not even number"<<endl;
}
else if(num%2==0)
{
j++;
}
else if(num%2 !=0) // Or just add a *else* here instead of *else if*, they will work exactly the same here.
{
c++;
}
} // End of for loop
cout<<"total exists even : "<<j<<endl;
cout<<"total exists ODD : "<<c<<endl;
return 0;
}
Firstly, 0 is an even number, and your code needs to be properly indented, just so you can see that you are indeed reading the input into a single integer, which also controls the loop, and your if statement is outside the for loop (despite the misleading indentation. Here's a simple example implementation, but you can (and should) fix the bugs I pointed out in your own code:
#include <iostream>
int main() {
std::cout << "Enter 5 numbers\n";
int cnt(5);
int n, odd(0), even(0);
while(cnt-- && (std::cin >> n))
n % 2 ? ++odd : ++even;
std::cout << odd << " odd, "
<< even << " even numbers" << std::endl;
return 0;
}
Note the post decrement and the fact the && short-circuits.
This should be your code:
you take an array of integer where you store the input value. Head over to https://www.tutorialspoint.com/cprogramming/c_arrays.htm to learn more abour arrays..
#include<iostream>
using namespace std;
int main(){
int i,j=0,c=0;
int numbers[5];
for(i=0;i<5;i++){
cout<<"enter 5 numbers "<<i ;
cin>>numbers[i];
}
for(i=0;i<5;++i){
if(numbers[i]==0)
{
cout<< "0 is not even number"<<endl;
}
else if(numbers[i]%2==0)
{j++;}
else if(numbers[i]%2 !=0)
{c++;}
}
cout<<"total exists even : "<<j<<endl;
cout<<"total exists ODD : "<<c<<endl;
return 0;
}
using namespace std;
int main()
{
int * Array = new int[5];
int even(0), odd(0);
for(int i = 0; i < 5; i++)
{
cout<<"enter "<< i+1 << "-th number: " << flush;
cin>>Array[i];
if(!Array[i])
{
cout<< "0 is not even number... input again"<<endl;
i = i-1;
}
else
{
if(Array[i]&1) odd++;
else even++;
}
}
cout<<"total exists even : "<<even<<endl;
cout<<"total exists ODD : "<<odd<<endl;
cin.get(); cin.get();
delete[] Array;
return 0;
}

C++ Letter Occurrences

Write a C++ program that reads input from a text file and counts the number of characters read from the input. If the character read is a letter ('a'-'z'), counts the number of times that letter occurs [using an array] (both uppercase and lowercase should be counted as the same letter) in the input. Output the percentage of each letter in the input text, as well as the percentage of non-letter characters in the input.
Yes, this is a homework question, and I have most of it, but for some reason it isn't adding like I'd hoped.
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
// make array with size of 26
// make array with all letter of alphabet
const int size = 26;
int narray[size];
char larray[26] = { 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z' };
// all variables
int count = 0;
char character;
int length = 0;
int amount = 0;
int sum = 0;
double percent = 0;
// open file user inputs
ifstream input;
string file;
cout << "Please enter the file to be read" << endl;
cin >> file;
input.open(file);
if (input.fail())
{
cout << "Can't open file successfully." << endl;
return 1;
}
// count amount of characters and spaces in while loop
while (!input.eof()) //loop until the file ends
{
getline(input, file); // read every character
int c = file.length(); // count length
length += c;
}
// make every variable in array equal to 0
for (count = 0; count < size; count++)
{
narray[count] = amount;
}
// make for loop to read every character
for (int i = 0; i < length; i++)
{
input.get(character); // read characters
if (character <= 'A' && character >= 'z')
{
narray[tolower(character)-'a']++; // find out which variable of the array it is and add 1 to the amount
sum++;
}
}
// make for loop to print out array percentages
for (int j = 0; j < size; j++)
{
percent = (narray[j] / length) * 100;
cout << larray[j] << " " << percent << "%" << endl;
}
int non = (((length - sum) / length) * 100);
cout << "Non letter characters " << non << "%" << endl;
input.close();
return 0;
}
Your code is a little more complicated than it needs to be, but worse it has several bugs in it.
You are using 2 separate loops to do the job that 1 loop can do.
You are calling input.eof() before you have performed a read operation. The stream's state is not updated until after a read is attempted, so calling eof() before the 1st read is undefined behavior.
After you have read through the stream one time to EOF just to count its characters, you are not seeking the stream back to the beginning so you can then read the characters all over again.
You are not counting line break characters in the 1st loop, but you are reading line break characters in the 2nd loop, so the 2nd loop (potentially) won't read as many characters as the 1st loop had counted.
You are not testing for Uppercase and Lowercase letters correctly, and you are not accounting for the fact that in ASCII, there are 6 non-letter characters between the set of Uppercase letters and set of Lowercase letters. Your indexing of the narray[] array is all wrong while you are counting characters.
You are not accounting for the possibility that the file might be completely empty, or have ONLY linebreak characters in it and no non-linebreak characters. If either of those condition happens, your length variable will be 0, and you would get errors when you calculate percentages when dividing by 0.
With that said, try something more like this instead:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
// make array with size of 26
const int size = 26;
int narray[size] = {}; // make every variable in array equal to 0
// all variables
char character;
int count = 0;
int sum_letters = 0;
int sum_non = 0;
double percent;
string file, line;
// prompt user for filename
cout << "Please enter the file to be read" << endl;
getline(cin, file);
// open file
ifstream input(file);
if (!input.is_open())
{
cout << "Can't open file." << endl;
return 1;
}
//loop until the file ends
while (getline(input, line))
{
count += line.size(); // count every character
for (int j = 0; j < line.size(); ++j)
{
character = line[j];
// find out which variable of the array it is and add 1 to the amount
if (character >= 'A' && character <= 'Z')
{
narray[character-'A']++;
++sum_letters;
}
else if (character >= 'a' && character <= 'z')
{
narray[character-'a']++;
++sum_letters;
}
else
++sum_non;
}
}
input.close();
if (count != 0)
{
// make for loop to print out array percentages
for (int j = 0; j < size; ++j)
{
percent = (double(narray[j]) / count) * 100.0;
cout << ('a'+j) << " " << percent << "%" << endl;
}
percent = (double(sum_non) / count) * 100.0;
cout << "Non letter characters " << percent << "%" << endl;
}
else
{
cout << "File has no characters" << endl;
}
return 0;
}
If you want to include line breaks in the percentage of non-letter characters, then use this instead:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
// make array with size of 26
const int size = 26;
int narray[size] = {}; // make every variable in array equal to 0
// all variables
char character;
int count = 0;
int sum_letters = 0;
int sum_non = 0;
double percent;
string file, line;
// prompt user for filename
cout << "Please enter the file to be read" << endl;
getline(cin, file);
// open file
ifstream input(file);
if (!input.is_open())
{
cout << "Can't open file." << endl;
return 1;
}
//loop until the file ends
while (input.get(character))
{
++count; // count every character
// find out which variable of the array it is and add 1 to the amount
if (character >= 'A' && character <= 'Z')
{
narray[character-'A']++;
++sum_letters;
}
else if (character >= 'a' && character <= 'z')
{
narray[character-'a']++;
++sum_letters;
}
else
++sum_non;
}
input.close();
if (count != 0)
{
// make for loop to print out array percentages
for (int j = 0; j < size; ++j)
{
percent = (double(narray[j]) / count) * 100.0;
cout << ('a'+j) << " " << percent << "%" << endl;
}
percent = (double(sum_non) / count) * 100.0;
cout << "Non letter characters " << percent << "%" << endl;
}
else
{
cout << "File is empty" << endl;
}
return 0;
}