ループの増加による致命的なエラー
-
28-09-2019 - |
質問
現在、Fighter.cppファイルの関数SortFightersのファイターでいっぱいのベクトルをソートする関数を作成しようとしています。それはすべて正しくコンパイルされているようです。ただし、実行すると、上記の.cppファイルの行の1つで致命的なエラーが発生します。私は問題が何であるかを正確に知っており、それに応じてそこにコメントを入れます。だから、私がここで尋ねているのは、他の機能などを追加せずにこの問題を解決するために私がするかもしれないことです。
これが私の戦闘機です。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;
}
解決
for (int i=0; i<=(x.size()); i++)
{
if(x[i].level > x[i+1].level)
{
um .. size()は1からカウントされます。インデックスは0からカウントされます。したがって、あなたはそれを作りたいです i < x.size()
, 、 いいえ <=
. だが, 、次の行で、あなたは言います x[i+1]
, 、 それで i
最後のアイテムに到達することさえできません。その前に停止する必要があります。
for (int i=0; i < x.size()-1; i++)
他のヒント
そのループを修正する方法についてのアドバイスを受けました。私のアドバイスは、それを排除して使用することです 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>
意思 いいえ 正しく読む(それ 必要 前後に少なくとも1つの空白 <fighter>
単一の文字列として読むため)。
これにループを変更してみてください
for (int i=0; i < x.size() - 1; i++) {
... your original content...
}
こちらです x[i+1]
境界が崩れないことはありません
割り当てられていないメモリにアクセスしようとしていました。
あなたの問題はこのループにあります:
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の境界の外側を比較しています。 if i == x.size()
それから x[i+1] > x.size()
私はあなたのループを変更して終了することをお勧めします i<(x.size())-1;
それよりも i<=(x.size());
他の人が言ったように、問題はコードのこのセクションです。
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
a 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
)コンパイラ警告を生成する場合があります(まだ行っていない場合は、そのようなコンパイラ警告をすべてオンにする必要があります)。 i
に unsigned
また size_t
:
for (size_t i = 0; i + 1 < x.size(); i++) {
最後に、独自のバブルソートをコーディングするよりも、使用する方が良いです std::sort
. std::sort
他のC ++開発者にとってより速く、より馴染みがあります。これが使用の(テストされていない)例です std::sort
:
bool CompareByLevel(const Fighter& a, const Fighter& b) {
return a.level < b.level;
}
sort(x.begin(), x.end(), CompareByLevel);
他のコメント: C ++についてもっと知りたい場合は、役立つ可能性のある他のコメントをいくつか紹介します。
inputFile >> line;
この声明は、実際に単一の白色または新しいライン分離された単語を読み取ります line
. 。それがあなたがやろうとしていることなら、変数名の選択(line
)それを伝えません。そして、あなたは戦闘機の名前で白人を使用できるようにすることを望むかもしれません。行全体を読むには、これを使用してください。 ここ 参考のために。)
getline(inputFile, line);
getEnemies
, printFighter
, 、 と sortFighters
あるべきです static
方法、彼らはの特定のインスタンスを必要としないので Fighter
操作する。 (今、それらは静的な方法ではないので、あなたは enemy
これらの方法を呼び出すための戦闘機のインスタンスは、これらの方法のいずれも何もしませんが enemy
.)
C ++では、動的に割り当てるのではなく、スタック上に変数を作成できます。言い換えれば、言う代わりに
Fighter * temp = new Fighter;
言うだけ
Fighter temp;
動的割り当てが必要ない場合、これはより速く、よりシンプルです。
最後に、C ++は、クラスのすべてのメンバーをコピーする割り当て演算子を作成します。だからあなたは単に書くことができます
temp = x[i];
Xの各メンバーを一時的に手動で割り当てる代わりに。割り当て演算子の使用は、後でメンバーを追加すると将来機能し続けるため、より堅牢です。 Fighter
.
お役に立てれば。