目前,我正在尝试制作一个功能,在Fighter.cpp文件的sortFighters函数中对一个充满战斗机的矢量进行排序。这一切似乎都正确编译;但是,当它运行时,我会在前面提到的.cpp文件的一行中出现致命错误。我确切地知道问题是什么,并在那里发表评论。 所以,我在这里问的是,如果不添加任何其他功能等,我可以采取哪些措施来解决这个问题。
这是我的Fighter.h文件:
#ifndef FIGHTER_H
#define FIGHTER_H
#include <iostream>
#include <ctime>
#include <string>
#include <cstdlib>
#include <fstream>
#include <vector>
class Fighter
{
protected:
std::string name;
int health, level;
//int damage;
public:
int getHealth(int);
void getEnemies(std::vector<Fighter> &);
void printFighter(std::vector<Fighter> &);
void sortFighters(std::vector<Fighter> &);
//friend std::istream & operator >> (std::istream & strm, Fighter & x);
//friend std::ostream & operator << (std::ostream & strm, const Fighter & f);
//void attack();
Fighter();
~Fighter();
};
class Player : public Fighter
{
private:
int experience;
public:
int getHealth(int);
void pri`enter code here`ntFighter();
void getExperience(int);
void playerAttack();
Player();
~Player();
};
//class FightPub
//{
// private:
// Player player;
// Fighter enemy;
// public:
// //void fight();
// //void getStats();
//};
#endif
我的Fighter.cpp文件:
//dynamically locate an array that holds the number of fighters, and for each fighter in the array, assign from the .txt
//file the name and level from the fighter.
#include "Fighter.h"
#pragma region getEnemies
void Fighter::getEnemies(std::vector<Fighter> &baddie)
{
Fighter x;
std::ifstream inputFile;
inputFile.open("EnemyFighters.txt");
if(!inputFile)
{
std::cout << "error!" << std::endl;
}
else
{
while(!inputFile.eof())
{
std::string line;
inputFile >> line;
if (line == "<fighter>")
{
do
{
inputFile >> line;
x.name = line;
inputFile >> line;
x.level = atoi(line.c_str());
inputFile >> line;
x.health = getHealth(this->level);
baddie.push_back(x);
inputFile >> line;
}while(line != "</fighter>");
}
}
inputFile.close();
}
}
#pragma endregion
#pragma region getHealth
int Fighter::getHealth(int lv)
{
if(lv >= 6)
{
std::cout << "\nHealth Bonus!";
this->health = lv * 2;
}
/*else if (lv > 1)
for (int i = 1; i < lv; i++)
{this->health += 2;}*/
return health;
}
#pragma endregion
#pragma region attack
//void Fighter::attack()
//{
// int randomAttack = rand() % 4 + 1;
//
// switch (randomAttack)
// case 1:
// {
// std::cout << "Enemy uses critical attack!"
// }
//}
#pragma endregion
#pragma region printFighter
void Fighter::printFighter(std::vector<Fighter> &baddie)
{
//std::cout << this;
for (int i=0; i<baddie.size(); i++)
{
std::cout << "\nName: " << baddie[i].name << std::endl
<< "Level: " << baddie[i].level << std::endl
<< "Health: " << baddie[i].health << std::endl;
}
}
#pragma endregion
void Fighter::sortFighters(std::vector<Fighter> &x)
{
Fighter * temp = new Fighter;
bool swap;
do
{
swap = false;
std::cout << x.size() << std::endl;
for (int i=0; i<=(x.size()); i++)
{
//if the level in the first is greater than the level in the next
if(x[i].level > x[i+1].level)//I get a fatal error here when it tries to compare
//the iterator with 1 that's outside its range
{
//assign the stats from the first to temp
temp->name = x[i].name;
temp->health = x[i].health;
temp->level = x[i].level;
//assign the stats from the next to the first
x[i].name = x[i+1].name;
x[i].health = x[i+1].health;
x[i].level = x[i+1].level;
//assign the ones in temp(the first) to the next
x[i+1].name = temp->name;
x[i+1].health = temp->health;
x[i+1].level = temp->level;
swap = true;
}
else if(x[i].level >= x[i+1].level)
{
temp->name = x[i].name;
temp->health = x[i].health;
temp->level = x[i].level;
x[i].name = x[i+1].name;
x[i].health = x[i+1].health;
x[i].level = x[i+1].level;
x[i+1].name = temp->name;
x[i+1].health = temp->health;
x[i+1].level = temp->level;
swap = true;
}
else if (x[i].level < x[i+1].level)
{
//temp->name = x[i].name;
//temp->health = x[i].health;
//temp->level = x[i].level;
//x[i].name = x[i+1].name;
//x[i].health = x[i+1].health;
//x[i].level = x[i+1].level;
//x[i+1].name = temp->name;
//x[i+1].health = temp->health;
//x[i+1].level = temp->level;
swap = false;
}
else if(x[i].level <= x[i+1].level)
{
/*temp->name = x[i].name;
temp->health = x[i].health;
temp->level = x[i].level;
x[i].name = x[i+1].name;
x[i].health = x[i+1].health;
x[i].level = x[i+1].level;
x[i+1].name = temp->name;
x[i+1].health = temp->health;
x[i+1].level = temp->level;*/
swap = false;
}
}
}while (swap);
delete temp;
}
//std::istream & operator >>(std::istream & strm, Fighter x)
//{
// //x.name += strm.c_str();
// //x.level += atoi(strm.c_str());
// strm >> x.name;
// strm >> x.level;
// return strm;
//}
//std::ostream & operator << (std::ostream & strm, const Fighter f)
//{
// strm << "Name: " << f.name << std::endl;
// strm << "Level: " << f.level << std::endl;
// strm << "Health: " << f.health << std::endl;
// return strm;
//}
#pragma region Fighter C&D
Fighter::Fighter()
{
level = 1;
health = 10;
}
Fighter::~Fighter()
{
}
#pragma endregion
//void operator <()
//{
//}
//
//void operator >()
//{
//}
//
//void operator <=()
//{
//}
//
//void operator >=()
//{
//}
//
//
//
int Player::getHealth(int lv)
{
if(lv >= 6)
{
std::cout << "\nHealth Bonus!";
this->health = lv * 2;
}
/*else if (lv > 1)
for (int i = 1; i < lv; i++)
{this->health += 2;}*/
return health;
}
void Player::printFighter()
{
//std::cout << this;
std::cout << "\nPlayer's stats: \n"
<< "Level: " << this->level << std::endl
<< "Health: " << this->health << std::endl
<< "Experience: " << this->experience <<std::endl;
}
void Player::getExperience(int dmg)
{
experience += dmg;
if (experience >= (level * 10))
{
std::cout << "Congratulations, Player! You're up a level!\n";
level ++;
}
}
#pragma region Player C&D
Player::Player()
{
level = 1;
health = getHealth(level);
experience = 0;
}
Player::~Player()
{
}
#pragma endregion
//Player::printFighter()
//{
//
//}
这是main.cpp:
#include "Fighter.h"
int main()
{
unsigned seed = time(0);
srand(seed);
std::vector<Fighter> baddie;
Fighter * enemy = new Fighter;
Player * me = new Player;
enemy->getEnemies(baddie);
enemy->sortFighters(baddie);
enemy->printFighter(baddie);
me->printFighter();
delete enemy;
delete me;
return 0;
}
答案 0 :(得分:3)
for (int i=0; i<=(x.size()); i++)
{
if(x[i].level > x[i+1].level)
{
嗯..大小()从1开始计数。索引从0开始计数。因此,您需要制作i < x.size()
,而不是<=
。 但是,在下一行中,您说x[i+1]
,因此i
甚至无法到达最后一个项目,它必须在此之前停止:
for (int i=0; i < x.size()-1; i++)
答案 1 :(得分:2)
您已经就如何修复该循环获得了一些建议。我的建议是消除它并改为使用std::sort
。
虽然我们正在处理没有正确终止的循环,但是也许值得一提(在getEnemies()
中):
while(!inputFile.eof())
{
std::string line;
inputFile >> line;
if (line == "<fighter>")
{
// ...
这也被打破了。要使循环正确终止,您需要读取数据,然后检查读取是否成功:
std::string line;
while (inputFile >> line) {
if (line == "<fighter>") {
// ...
可能还值得注意的是,此代码非常脆弱 - 仅举一例,例如:<fighter>fighter1</fighter>
无法正确读取(需要 > <fighter>
之前和之后至少有一个空格,将其作为单个字符串读取。)
答案 2 :(得分:0)
尝试将for循环更改为此
for (int i=0; i < x.size() - 1; i++) {
... your original content...
}
这种方式x[i+1]
永远不会超出范围
您试图访问尚未分配的内存。
答案 3 :(得分:0)
你的问题在于这个循环:
for (int i=0; i<=(x.size()); i++){
if(x[i].level > x[i+1].level){ //Fatal Error Here
// Do some stuff
}
// Do some more stuff
}
终止外循环的条件是i<=(x.size())
这意味着当你进行比较(x[i+1].level
)打破程序时,你正在x之外进行比较。因为i == x.size()
然后是x[i+1] > x.size()
我建议您将循环更改为i<(x.size())-1;
而不是i<=(x.size());
答案 4 :(得分:0)
正如其他人所说,问题在于这部分代码:
for (int i=0; i<=(x.size()); i++)
{
//if the level in the first is greater than the level in the next
if(x[i].level > x[i+1].level)//I get a fatal error here when it tries to compare
//the iterator with 1 that's outside its range
std::vector
可以按值0到size() - 1
进行索引。因此,对于基本vector
循环,您应该改为
for (int i = 0; i < x.size(); i++) {
但是,在下一行代码中,你检查元素i + 1,所以你应该改为
for (int i = 0; i < x.size() - 1; i++) {
但是,因为x.size()是无符号的,如果x为空,那么x.size() - 1
将是一个非常大的数字(在32位机器上为2 ^ 32 - 1)。所以你应该为此调整逻辑。此外,将有符号值(如int i
)与无符号值(如x.size() - 1
)进行比较可能会生成编译器警告(如果尚未执行此操作,则应启用所有此类编译器警告),因此请更改{ {1}}至i
或unsigned
:
size_t
最后,不要编写自己的冒泡排序,最好使用std::sort
。 for (size_t i = 0; i + 1 < x.size(); i++) {
对其他C ++开发人员来说更快,更熟悉。这是使用std::sort
的一个(未经测试的)示例:
std::sort
其他评论:如果您有兴趣了解有关C ++的更多信息,可以参考以下其他一些评论。
bool CompareByLevel(const Fighter& a, const Fighter& b) {
return a.level < b.level;
}
sort(x.begin(), x.end(), CompareByLevel);
此语句实际上将单个空白或换行符分隔的单词读入inputFile >> line;
。如果那是你要做的事情,那么你选择的变量名称(line
)就不会传达这一点。而你可能希望能够使用战士名字中的空白。要阅读整行,请使用:(请参阅here以供参考。)
line
getline(inputFile, line);
,getEnemies
和printFighter
应该是sortFighters
方法,因为它们不需要static
的特定实例来操作。 (现在,因为它们不是静态方法,你必须创建一个Fighter
Fighter实例才能调用这些方法,即使这些方法都没有对enemy
做任何事情。)
C ++允许您在堆栈上创建变量,而不是动态分配它们。换句话说,而不是说
enemy
只是说
Fighter * temp = new Fighter;
如果您不需要动态分配,这会更快更简单。
最后,C ++将为您创建复制所有类成员的赋值运算符。所以你可以简单地写
Fighter temp;
而不是手动将每个x的成员分配给temp。使用赋值运算符更加强大,因为如果稍后将成员添加到temp = x[i];
,它将在将来继续有效。
希望这有帮助。