I am trying to make a very simple memory game and i'm having the following problem with vectors.
Expression cannot seek vector iterator after end
here is my code
#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
using namespace std;
void play();
void filler();
char faceup(int);
vector<char> cards (50);
int candy= 0;
int main()
{
filler();
play();
}
char faceup(int C) {
return cards[C];
}
void play() {
int n,l;
char p, s;
for (int i = 0; i < cards.size(); i++)
{
cout << cards[i];
}
cout << endl;
while (candy<50)
{
cout << "choose first card"<<endl;
cin >> n;
cout << "choose second card"<<endl;
cin >> l;
if (l == n) {
cout << "the cards are the same, try it again"<<endl;
}
else
{
p = faceup(n);
s = faceup(l);
cout << "The first card is: " + p;
cout << "The second card is: " + s;
if (s==p)
{
candy++;
cards.erase(cards.begin()+s);
cards.erase(cards.begin() + p);
}
}
}
}
void filler() {
//random_device rd;
//default_random_engine rng(rd());
int accountant = 0;
for (int i = 0; i < cards.size()/2; i++)
{
for (int o = 0; o < 2; o++) {
cards[accountant] = i+65;
accountant++;
}
}
//shuffle(cards.begin(), cards.end(), rng);
}
the error occurs with any integer that I type. I used the compiler of visual studio, then i used dev c++. In all cases I got the same or similar error
Thanks a million in advance
In your code, in line 11, you defined a vector whose length is equal to 50, and if we give our vector a number outside the numbers 0 to 49, the program should not run.
That you encountered the error I mentioned above in lines 48 and 49 of your program.
For example, if the user enters his card number 0 and 1, the sizes s and p are equal to 66, and lines 48 and 49 say to go to our vector index 66, which creates a problem for running our program.
enter code here
//////////error/////////////////////////
cards.erase(cards.begin()+s);
cards.erase(cards.begin() + p);
//////////error/////////////////////////
Related
I need to take 200 randomizes numbers from a file, separate them into even and odd, and make them show up from lowest to highest in their even or odd parts.
I got the code for making it into even and odd from here but the original way had 10 instead of 200 and made the user input the numbers.
I reworked it into this but I get a repeat of the same number then an error that reads Exception thrown: write access violation with a mark near the odd[oddcnt++] = arr[i];
My code so far
#include <iostream>
#include <fstream>
using namespace std;
class Random
{
private:
int x, arr[200], even[200], odd[200], evncnt = 0, oddcnt = 0, i;
public:
void readFile();
};
void Random::readFile()
{
fstream File("Random.txt");
if (File.is_open())
{
while(File >> x)
{
for (i = 0; i < 200; i++)
{
arr[i] = x;
}
for (i = 0; i < 200; i++)
{
if (arr[i] % 2 == 0)
{
even[evncnt++] = arr[i];
}
else
{
odd[oddcnt++] = arr[i];
}
}
cout << "\n The even numbers are: ";
for (i = 0; i < evncnt; i++)
{
cout << even[i] << "";
}
cout << "\n The odd numbers are: ";
for (i = 0; i < oddcnt; i++)
{
cout << odd[i] << "";
}
}
File.close();
}
}
int main()
{
Random file;
file.readFile();
system("pause");
return 0;
}
Your loops are all wrong. This is how it should look
i = 0;
while (file >> x)
{
arr[i] = x;
i++;
}
for (i = 0; i < 200; i++)
{
if (arr[i]%2==0)
...
}
If you put one loop inside another (like you did) then the inner loop executes fully every time the outer loop executes once. That's not what you want (in this case).
The answer is given already by John. So everything OK.
Additionally, I would like to show you the power of modern C++. Especially with using algorithms. You can write very elegant solutions.
Thers is no loop and only vey few variables.
You will of course not copy and paste it, because you will not understand it fully. But it should give you an idea how such a problem could be analysed, then designed, and then coded.
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
#include <vector>
#include <string>
class Random {
std::vector<int> values{};
public:
void readFile(const std::string& fileName);
void printOdds();
void printEvens();
};
void Random::readFile(const std::string& fileName) {
// Open file and check, if it could be opened
if (std::ifstream inputFileStream(fileName); inputFileStream) {
// Clear old content in our class
values.clear();
// Copy the contents from the vile into our vector
std::copy(std::istream_iterator<int>(inputFileStream), {}, std::back_inserter(values));
// sort the values
std::sort(values.begin(), values.end());
}
else { // File could not be opened
std::cerr << "\n*** Error: File could not be opened: " << fileName << "\n\n";
}
}
// Copy all odd values to std::cout
void Random::printOdds() {
std::copy_if(values.begin(), values.end(), std::ostream_iterator<int>(std::cout, " "), [](const int i) { return (i % 2) != 0; });
std::cout << "\n\n";
}
// Copy all even values to std::cout
void Random::printEvens() {
std::copy_if(values.begin(), values.end(), std::ostream_iterator<int>(std::cout, " "), [](const int i) { return (i % 2) == 0; });
std::cout << "\n\n";
}
// Driver code
int main() {
Random r;
r.readFile("r:\\random.txt");
r.printEvens();
r.printOdds();
return 0;
}
I am currently working on a project that displays a table after reading the contents and dimensions of the table from a text file.
The contents of puzzle.txt:
5 5
ferac
asdvb
mfkgt
opemd
welsr
I want my program to read the left number and store it in the variable numRow, and the right number in numCol, then read the letters into the puzzle array. However, when the dimension numbers print, they print as 0 0 instead of 5 5, and the puzzle array only outputs empty box characters.
#include <iostream>
#include <map>
#include <fstream>
#include <cstring>
#include <string>
using namespace std;
char puzzle [numRow][numCol];
void initializePuzzle() {
string storeInput;
int numRow, numCol;
cout << "What is the name of the file?" << endl;
getline(cin, storeInput);
ifstream inFile (storeInput);
inFile.open(storeInput.c_str());
for (int c = 0; c < sizeof(storeInput); c++) {
if (c == 0) {
inFile >> numRow >> numCol;
cout << numRow << ' ' << numCol << endl;
}
}
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
inFile >> puzzle[i][j];
}
}
}
void displayPuzzle() {
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
cout << puzzle[i][j];
}
cout << endl;
}
}
int main() {
initializePuzzle();
displayPuzzle();
return 0;
}
You can do this just by using the C++ Standard Library. Try this: (See about std::copy(), std::array and std::vector...)
#include <iostream> // For std::cout, std::endl, etc.
#include <fstream> // For std::ifstream
#include <vector> // For std::vector
#include <iterator> // For std::ostream_iterator
int main() {
std::string file_src;
// Ask for file name...
std::cout << "What is the name of the file? " << std::endl;
std::getline(std::cin, file_src);
// Declare the file stream...
std::fstream reader(file_src);
// Terminate the program with value '1' in case of failure when reading file...
if (reader.fail()) return 1;
// Declaring necessary varibles...
unsigned num_row, num_column;
std::string temporary;
/* Extracting 'num_row' and 'num_column' and declaring a 'std::vector' (which are
better than dynamic arrays in numerous ways) with the dimensions... */
reader >> num_row >> num_column;
std::vector<std::vector<char>> puzzle(num_row, std::vector<char>(num_column));
// Iterating over each line and copying the string where required...
for (auto i = 0; std::getline(reader, temporary, '\n') && i < num_row; i++)
if (!temporary.empty())
std::copy(temporary.begin(), temporary.end(), puzzle[i].begin());
else --i;
// Close the stream...
reader.close();
// Print the resulting vector...
for (auto & elem : puzzle) {
std::copy(elem.begin(), elem.end(), std::ostream_iterator<char>(std::cout, " "));
std::cout << std::endl;
}
return 0;
}
Example:
Input:
puzzle.txt
Output:
f e r a c
a s d v b
m f k g t
o p e m d
w e l s r
Hey guys I have a question about my code. Here's what we have to do:
"Ask the user to read a file. The file will be in the same format as “items.txt” on the website. There will
always be a list of items with a name and price followed by some amount of recipes. If a recipe for an
item is not present, the only way to make the item is to buy it directly. Make a program that reads all
the items and recipes, then says how much profit can be made by making each item.
If an item has no recipe, you would buy that item then resell it for the same price and make a profit of
0. If an item does have a recipe, you would buy the materials to make this item and subtract this cost
from the price of the final product.
There will only be zero or one recipe per item. The items will always be listed first. The names of
items will always be a single word (using a _ to join names that are normally multiple words). You
may assume there will be less than 50 items and each recipe will use less than 50 other items to create a
final product."
This is the items1.txt we use
Item: Wood 2.5
Item: Metal 5.5
Item: Cat 900
Item: Spear 50.7
Recipe: Spear = Wood + Wood + Metal ;
I have what I think would work but I can't get a certain line to work. I'm trying to use stod but apparently my school's computers don't support it. I also tried boost lexical cast and that wouldn't work either.
It says "stod: was not declared in this scope.
Here's my code:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <algorithm>
#include <sstream>
using namespace std;
string nextstring(string str, int start_index);
int split(string str, string a[], int max_size);
int main()
{
ifstream in_stream;
string fileName;
cout << "Enter the file name : ";
cin >> fileName;
in_stream.open(fileName.c_str());
//error checking
if (in_stream.fail())
{
cout << "File could not be opened." << endl;
exit(1);
}
string items[50];
double items_value[50];
string recipe[50];
string rname = recipe[0];
double profit = 0;
int j = 0;
string lines;
int number_of_lines = 0;
while(getline(in_stream, lines))
{
if(lines.substr(0,5) == "Item:")
{
int beginning = lines.find_first_of(' ') + 1;
int next_space = lines.find(" ", beginning);
items_value[j] = stod(lines.substr(next_space));
items[j] = lines.substr(beginning,lines.find_first_of(' ', beginning) - beginning);
j++;
}
if(lines.substr(0,7) == "Recipe:")
{
int max_size = lines.length();
int cnt = split(lines,recipe,max_size);
double profit1 = 0;
double profit2 = 0;
for(int j = 3; j < cnt; j++)
{
for(int i = 0; i < 4; i++)
{
if((recipe[j] == items[i]) && (recipe[j] != "+")&& (recipe[j] != ";"))
{
cout << "Making " << items[i] << ", " << "profit = 0" << endl;
profit1 += items_value[i];
}
if(recipe[1] != items[i])
{
profit2 = 0;
}
}
}
for(int i = 0; i < cnt; i++)
{
if((recipe[1] == items[i]))
{
profit = items_value[i];
cout << "Making " << items[i] << ", " << "profit = ";
}
}
cout << profit - profit1 << endl;
}
}
in_stream.close();
return 0;
}
string nextstring(string str, int start_index)
{
int y =0;
y = str.find(' ',start_index);
y = y-start_index;
str = str.substr(start_index,y);
return str;
}
int split(string str, string a[], int max_size)
{
int i;
int num = 0;
for (i=0; i<max_size; i++)
{
a[i] = nextstring(str,num);
num = num + a[i].length() + 1;
if(num >= str.length())
{
i++;
break;
}
}
return i;
}
First step is get a decent compiler from this century ;) stod has been available since c++11, which really means that it was available probably a few years before that.
If stod isn't available to you then you can revert to the cstdlib function atof.
So, I'm trying bring over some code to a Qt project I'm working on. The Motion class imports some control points from .txt file into the public member variable ctrlPos using fstream. When I use readCtrlPositions and then try to access ctrlPos with writePositions, for example, I get the error "vector subscript out of range".
There is a lot more code, but hopefully this should be sufficient to answer my question. I'm also a bit of a novice, so with any luck it's not something too stupid.
Motion class header:
#ifndef MOTION_H
#define MOTION_H
#include <vector>
#include "DualQuaternion.h"
class Motion
{
public:
virtual ~Motion();
virtual void readCtrlPositions(char*, char*);
virtual void writePositions(char*);
virtual void drawCtrlPositions();
virtual void set(int, vector<DualQuaternion>);
virtual pair<int, vector<DualQuaternion>> get();
public:
vector<DualQuaternion> ctrlPos, c;
int numberOfPositions;
};
#endif
Motion class:
#include <stdlib.h>
#include <GL\glut.h>
#include "motion.h"
#include "Quaternion.h"
#include "hMatrix.h"
#include "hPoint.h"
using namespace std;
void Motion::readCtrlPositions(char *fileNameArg, char *t)
{
ifstream inFile(fileNameArg, ios::in);
if (!inFile)
{
cerr<<"File" << fileNameArg << "could not be opened" << endl;
exit(1);
}
int i;
inFile >> numberOfPositions;
Quaternion *RotationQuaternion = new Quaternion[numberOfPositions];
for (i = 0; i<numberOfPositions; i++)
inFile >> RotationQuaternion[i];
if (t == "v")
{
Vector *TranslationVector = new Vector[numberOfPositions];
for (i = 0; i<numberOfPositions; i++)
inFile >> TranslationVector[i];
ctrlPos.clear();
for (i = 0; i<numberOfPositions; i++)
{
DualQuaternion dQ(RotationQuaternion[i], TranslationVector[i]);
ctrlPos.push_back(dQ);
cout << "first position from input: " << ctrlPos[i] << endl;
}
delete[] TranslationVector;
}
else if (t == "q")
{
Quaternion *TranslationQuaternion = new Quaternion[numberOfPositions];
for (i = 0; i<numberOfPositions; i++)
inFile >> TranslationQuaternion[i];
ctrlPos.clear();
for (i = 0; i<numberOfPositions; i++)
{
DualQuaternion dQ(RotationQuaternion[i], TranslationQuaternion[i]);
ctrlPos.push_back(dQ);
cout << "first position from input: " << ctrlPos[i] << endl;
}
delete[] TranslationQuaternion;
}
delete[] RotationQuaternion;
}
void Motion::writePositions(char *fileNameArg)
{
ofstream outFile(fileNameArg, ios::out);
if (!outFile)
{
cerr<<"File" << fileNameArg << "could not be opened for writing" << endl;
exit(1);
}
int i;
outFile << numberOfPositions << endl << endl;
for (i = 0; i<numberOfPositions; i++)
outFile << ctrlPos[i].GetReal();
outFile << endl;
for (i = 0; i<numberOfPositions; i++)
outFile << ctrlPos[i].GetDual();
}
void Motion::set(int n, vector<DualQuaternion> p)
{
int i;
numberOfPositions = n;
ctrlPos.clear();
for (i = 0; i<numberOfPositions; i++)
ctrlPos.push_back(p[i]);
}
pair<int, vector<DualQuaternion>> Motion::get()
{
return make_pair(numberOfPositions, ctrlPos);
}
void Motion::drawCtrlPositions()
{
vector <hMatrix> homogeneousMatricesForCtrlPositions;
for (int i=0; i<numberOfPositions; i++)
{
homogeneousMatricesForCtrlPositions.push_back(ctrlPos[i].dualQuaternionToHomogeneousMatrix().transpose());
double MatrixforOpenGLStack[16];
for (int i1=0; i1<4; i1++)
for (int i2=0; i2<4; i2++)
MatrixforOpenGLStack[4*i1+i2] = homogeneousMatricesForCtrlPositions.at(i).m[i1][i2];
::glPushMatrix();
::glMultMatrixd(MatrixforOpenGLStack);
glutSolidTeapot(0.15);
::glPopMatrix();
}
}
Motion::~Motion()
{
}
Sample code where error occurs in Qt program:
static Curve m;
m.readCtrlPositions("input.txt", "v");
m.writePositions("output.txt"); //<--vector subscript out of range
m.readCtrlPositions("output.txt", "q");
ctrlPos = m.get().second;
numberOfPositions = m.get().first;
In readCtrlPositions, t is a char*, so nor t=="v", nor t=="q" will be evaluated to true (it would return true if the two pointers were having the same address). So your function will set numberOfPositions to a non zero value but will never fill ctrlPos vector with any value.
Later, you'll try to access ctrlPos elements from 0 to numberOfPositions (not zero), while ctrlPos vector is empty. That's why you are reported to access the vector out of its range!
Replace char* by std::string is an easy way to fix the problem. If you need to keep the parameter as a char*, then use strcmp to compare string values rather than pointers.
I would also strongly recommend that you remove your numberOfPositions attribute and simply use ctrlPos.size() instead. It would have prevented a crash in this case by guaranteeing your class attributes integrity.
i am creating a somekind of rpg battle, where the program reads the input from a .txt file. i created the code but when i want to start the battle, it gave me an error vector subscript out of range. can anyone help me how to fix this? thank you very much :) here is the code. I included everything just so you could get a full context but the main problem I believe is in my while loop in the main cpp, if you want to just skip down to there.
and so that we are on the same track, the content of the txt file for lamanite(hitpoints and regen points) is
8 2
7 3
6 1
for nephite its
10 3
12 4
11 5
here is my warrior.h file
#pragma once
#include <string>
using namespace std;
class warrior
{
public:
warrior ();
warrior (int h, int r);
int getDamage() const;
void takeDamage(int damage);
int getCurrentHP() const;
void regenerate();
string tostring(int h, int r);
private:
int HitPoints;
int RegPoints;
int damage;
};
here is my warrior cpp
#include "warrior.h"
#include <string>
#include <iostream>
warrior::warrior(int h, int r)
{
HitPoints = h;
RegPoints = r;
}
int warrior::getDamage() const
{
int damage = rand () % HitPoints;
return damage;
}
void warrior::takeDamage(int damage)
{
HitPoints = HitPoints - damage;
}
int warrior::getCurrentHP() const
{
return HitPoints;
}
void warrior::regenerate()
{
HitPoints = HitPoints + rand () % (RegPoints);
}
string warrior::tostring(int h, int r)
{
return 0;
}
my main file
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <ctime>
#include "warrior.h"
using namespace std;
void main ()
{
srand(time(0));
ifstream input1;
cout << "input file name nephite: ";
string filename;
cin >> filename;
input1.open(filename);
int HP1, RP1;
vector <warrior*> nephites;
while (input1 >> HP1 >> RP1)
{
nephites.push_back(new warrior(HP1, RP1));
}
cout << nephites.size() << endl;
ifstream input2;
cout << "input file name lamanite : ";
string filename2;
cin >> filename2;
input2.open(filename2);
int HP2, RP2;
vector <warrior*> lamanites;
while (input2 >> HP2 >> RP2)
{
lamanites.push_back(new warrior(HP2, RP2));
}
cout << lamanites.size() << endl;
cout << endl << "Battle" << endl;
warrior nephitesw = warrior (HP1,RP1);
warrior lamanitesw = warrior (HP2,RP2);
while ((nephites.size() > 0) && (lamanites.size() > 0))
{
int rN = rand () % nephites.size();
int rL = rand () % lamanites.size();
cout << rN << "xx" << rL << endl; // so that i know what rN and rL is
while((nephites[rN]->getCurrentHP() > 0) && (lamanites[rL]->getCurrentHP() > 0)) // the program can't execute this part of the code
{
nephites[rN]->takeDamage(lamanites[rL]->getDamage());
lamanites[rL]->takeDamage(nephites[rN]->getDamage());
if(lamanites[rL]->getCurrentHP() > 0)
{
lamanites[rL]->regenerate();
}
else
{
lamanites.erase(lamanites.begin() + (rL));
}
if(nephites[rN]->getCurrentHP() > 0)
{
nephites[rN]->regenerate();
}
else
{
nephites.erase(nephites.begin() + (rN));
}
}
cout << "NEP HP: " << nephites[rN]->getCurrentHP() << " " << "LAM HP: " << lamanites[rL]->getCurrentHP() << endl;
}
system ("Pause");
}
You have a while loop that tests for a certain properties of nephites[rN] and lamanites[rL]:
while((nephites[rN]->getCurrentHP() > 0) && (lamanites[rL]->getCurrentHP() > 0)
{
// ...
}
But inside that loop you might erase those elements:
{lamanites.erase(lamanites.begin() + (rL));}
// ...
{nephites.erase(nephites.begin() + (rN));}
At the very least, after one of those erase operations you'll be testing a different nephite or lamanite object on the next loop iteration (which may or may not be what you want), but if you've erased the last element in the container, you have the problem that the index is now out of range.
You are looping until either nephites[rN]->getCurrentHP() <= 0 or lamanites[rL]->getCurrentHP() <= 0. However, whichever one drops to 0 first will be deleted from the vector:
// ...
{lamanites.erase(lamanites.begin() + (rL));}
// ...
{nephites.erase(nephites.begin() + (rN));}
If rN == nephites.size() or rN == lamanites.size() (which will definitely happen when the size is 1 and may randomly happen earlier), this will cause you to index out of the vector when you test the loop.
To quickly solve the problem, move the code that removes the warrior(s) from the vector out of the loop:
while((nephites[rN]->getCurrentHP() > 0) && (lamanites[rL]->getCurrentHP() > 0))
{
nephites[rN]->takeDamage(lamanites[rL]->getDamage());
lamanites[rL]->takeDamage(nephites[rN]->getDamage());
if(lamanites[rL]->getCurrentHP() > 0)
{
lamanites[rL]->regenerate();
}
if(nephites[rN]->getCurrentHP() > 0)
{
nephites[rN]->regenerate();
}
}
cout << "NEP HP: " << nephites[rN]->getCurrentHP() << " " << "LAM HP: " << lamanites[rL]->getCurrentHP() << endl;
// *****
// Move the erasures out of the loop
// *****
if(lamanites[rL]->getCurrentHP() <= 0)
{
lamanites.erase(lamanites.begin() + (rL));
}
if(nephites[rN]->getCurrentHP() <= 0)
{
nephites.erase(nephites.begin() + (rN));
}