2

現在、Fighter.cpp ファイルの関数 sortFighters で、戦闘機でいっぱいのベクトルを並べ替える関数を作成しようとしています。すべてが正しくコンパイルされているようです。ただし、実行すると、前述の .cpp ファイルの行の 1 つで致命的なエラーが発生します。私は問題が何であるかを正確に知っており、それに応じてコメントを入れています。だから、私がここで尋ねているのは、他の機能などを追加せずにこの問題を解決するために私ができることです。

ここに私の 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;
}
4

5 に答える 5

3
    for (int i=0; i<=(x.size()); i++) 
    { 
        if(x[i].level > x[i+1].level)
        {

ええと.. Size() は 1 から数えます。インデックスは 0 から数えi < x.size()ます<=しかし、非常に次の行で、あなたは言うx[i+1]のでi、最後の項目に到達することさえできず、その前に 1 つ停止する必要があります。

    for (int i=0; i < x.size()-1; i++) 
于 2010-08-16T14:45:25.347 に答える
2

そのループを修正する方法についていくつかのアドバイスがあります。私のアドバイスは、それを削除してstd::sort代わりに使用することです。

ただし、正しく終了しないループを扱っている間は、おそらくもう1つ(で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>

于 2010-08-16T15:00:42.250 に答える
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

Aは、 std::vector0からまでの値でインデックスを付けることができます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ますunsignedsize_t

for (size_t i = 0; i + 1 < x.size(); i++) {

最後に、独自のバブルソートをコーディングするのではなく、を使用することをお勧めしますstd::sortstd::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およびsortFightersstaticメソッドである必要があります。これは、操作するためにの特定のインスタンスを必要としないためFighterです。(現時点では、これらは静的メソッドではないため、enemyこれらのメソッドを呼び出すには、Fighterのインスタンスを作成する必要があります。ただし、これらのメソッドはいずれも処理しませんenemy。)

C ++では、変数を動的に割り当てるのではなく、スタック上に変数を作成できます。言い換えれば、言う代わりに

Fighter * temp = new Fighter;

言うだけ

Fighter temp;

動的な割り当てが必要ない場合、これはより高速で簡単です。

最後に、C ++は、クラスのすべてのメンバーをコピーする代入演算子を作成します。だからあなたは簡単に書くことができます

temp = x[i];

xの各メンバーを手動でtempに割り当てる代わりに。代入演算子の使用は、後でメンバーをに追加した場合でも将来も機能し続けるため、より堅牢ですFighter

お役に立てれば。

于 2010-08-16T14:59:33.717 に答える
0

forループをこれに変更してみてください

for (int i=0; i < x.size() - 1; i++) {
  ... your original content...
}

この方法x[i+1]では範囲外にはなり
ません 割り当てられていないメモリにアクセスしようとしました。

于 2010-08-16T14:46:54.877 に答える
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());

于 2010-08-16T14:47:47.307 に答える