递增循环的致命错误
目前,我正在尝试创建一个函数,在 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;
}
Currently, I'm trying to make a function that sorts a vector full of fighters in the function sortFighters in the Fighter.cpp file. It all seems to compile correctly; However, when it does run, I get a fatal error in one of the lines of the aformentioned .cpp file. I know exactly what the problem is, and put a comment there accordingly.
So, what I'm asking here, is what I might do to fix this problem without adding any other functions and such.
Here's my Fighter.h file:
#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
My Fighter.cpp file:
//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()
//{
//
//}
And here's 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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
嗯.. Size() 从 1 开始计数。索引从 0 开始计数。所以你需要让
i
i
i
i
i
i
i
i
i
i
i
i
i x.size()
,而不是<=
。 但是,在下一行中,你说x[i+1]
,所以i
甚至无法到达最后一项,它必须在此之前停下来:um.. Size() counts from 1. Indexes count from 0. So you'll want to make that
i < x.size()
, not<=
. But, in the very next line, you sayx[i+1]
, soi
can't even reach the last item, it has to stop one before that:您已经获得了一些有关如何修复该循环的建议。我的建议是消除它并使用 std::sort 代替。
然而,当我们处理未正确终止的循环时,可能还值得一提的是(在
getEnemies()
中):这也被破坏了。为了正确终止循环,您需要读取数据,然后检查读取是否成功:
可能还值得注意的是,这段代码非常脆弱——仅举一个例子,例如:
; fighter1
将无法被正确读取(它需要在
前后至少有一个空格将其作为单个字符串读取)。You've gotten some advice about how to fix that loop. My advice would be to eliminate it and use
std::sort
instead.While we're dealing with loops that don't terminate correctly, however, it's probably also worth mentioning one other (in
getEnemies()
):This is broken as well. For the loop to terminate correctly, you need to read the data, and then check whether the read succeeded:
It's probably also worth noting that this code is pretty fragile -- just for one example, something like:
<fighter>fighter1</fighter>
will not be read correctly (it requires at least one whitespace before and after<fighter>
to read it as a single string).尝试将 for 循环更改为这样
x[i+1]
永远不会超出范围您试图访问尚未分配的内存。
Try Changing your for loop to this
This way
x[i+1]
never goes out of boundsYou were trying to access memory that has not been allocated.
您的问题出在这个循环上:
终止外循环的条件是
i<=(x.size())
这意味着当您进行比较时 (x[i+1] .level
)会破坏程序,您正在比较 x 的范围之外。因为如果i == x.size()
则x[i+1] > x.size()
我建议更改循环以在
i<(x.size())-1;
终止,而不是i<=(x.size() );
Your problem is with this loop:
Your condition for terminating the outer loop is
i<=(x.size())
this means that when you do the comparision (x[i+1].level
) that breaks the program, you are comparing outside the bounds of x. Because ifi == x.size()
thenx[i+1] > x.size()
I reccomend changing your loop to terminate at
i<(x.size())-1;
rather thani<=(x.size());
正如其他人所说,问题在于这一段代码:
std::vector
可以通过值 0 到size() - 1
(含)进行索引。因此,对于基本的向量循环,您应该执行BUT,在下一行代码中,您检查元素 i + 1,因此您应该执行
BUT,因为 x.size() 是无符号的,如果 x 为空,则 x.size() - 1 将是一个非常大的数字(在 32 位机器上为 2^32 - 1)。所以你应该为此调整逻辑。此外,将有符号值(如 int i 与无符号值(如 x.size() - 1 )进行比较可能会生成编译器警告(您应该打开所有此类编译器警告,如果您还没有这样做),请将
i
更改为unsigned
或size_t
:最后,不是编写您自己的冒泡排序,而是最好使用
std::sort
。 >std::sort 速度更快,对于其他 C++ 开发人员来说也更熟悉,这是一个使用std::sort
的(未经测试的)示例:其他评论: 如果。 如果您有兴趣了解有关 C++ 的更多信息,这里有一些其他注释可能会有所帮助。
此语句实际上将单个空格或换行符分隔的单词读取到
line
中。这样做,那么您选择的变量名称(line
)并不能传达这一点,并且您可能希望能够在战士的名称中使用空格。要读取整行,请使用以下命令:(请参阅此处以供参考。)< code>getEnemies、
printFighter
和sortFighters
应该是static
方法,因为它们不需要的特定实例code>Fighter
进行操作。 (现在,因为它们不是静态方法,所以您必须创建 Fighter 的enemy
实例才能调用这些方法,即使这些方法都不会对enemy
执行任何操作code>.)C++ 允许您在堆栈上创建变量,而不是动态分配它们。换句话说,
而不是仅仅说
如果您不需要动态分配,
这更快更简单。最后,C++ 将为您创建复制所有类成员的赋值运算符。因此,您可以简单地编写
而不是手动将 x 的每个成员分配给 temp。使用赋值运算符更加可靠,因为如果您稍后将成员添加到
Fighter
,它将在将来继续工作。希望这有帮助。
The problem, as others have said, is this section of code:
A
std::vector
can be indexed by values 0 throughsize() - 1
, inclusive. So, for a basicvector
loop, you should instead doBUT, in the next line of code, you check element i + 1, so you should instead do
BUT, because x.size() is unsigned, if x is empty, then
x.size() - 1
will be a very large number (2^32 - 1 on a 32-bit machine). So you should adjust the logic for this. Also, comparing signed values (likeint i
against unsigned values (likex.size() - 1
) may generate compiler warnings (you should turn all such compiler warnings on, if you haven't already done so), so changei
tounsigned
orsize_t
:Finally, rather than coding your own bubble sort, it's better to use
std::sort
.std::sort
is faster and more familiar to other C++ developers. Here's an (untested) example of usingstd::sort
:Other comments: If you're interested in learning more about C++, here are a few other comments that might help.
This statement actually reads a single whitespace- or newline-separated word into
line
. If that's what you're trying to do, then your choice of variable name (line
) doesn't communicate that. And you may want to be able to use whitespace in fighters' names. To read an entire line, use this: (See here for reference.)getEnemies
,printFighter
, andsortFighters
should bestatic
methods, since they don't need a particular instance of aFighter
to operate on. (Right now, because they're not static methods, you have to create anenemy
instance of Fighter in order to call those methods, even though none of those methods do anything withenemy
.)C++ lets you create variables on the stack, instead of dynamically allocating them. In other words, instead of saying
just say
This is faster and simpler, if you don't need dynamic allocation.
Finally, C++ will create assignment operators for you that copy all of a class's members. So you could simply write
instead of manually assigning each of x's members to temp. Using the assignment operator is more robust, since it will continue to work in the future if you later add members to
Fighter
.Hope this helps.