递增循环的致命错误

发布于 2024-09-14 09:09:40 字数 8652 浏览 24 评论 0原文

目前,我正在尝试创建一个函数,在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

青瓷清茶倾城歌 2024-09-21 09:09:40
    for (int i=0; i<=(x.size()); i++) 
    { 
        if(x[i].level > x[i+1].level)
        {

嗯.. Size() 从 1 开始计数。索引从 0 开始计数。所以你需要让 i i i i i i i i i i i i i x.size(),而不是 <=但是,在下一行中,你说x[i+1],所以i甚至无法到达最后一项,它必须在此之前停下来:

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

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 say x[i+1], so i can't even reach the last item, it has to stop one before that:

    for (int i=0; i < x.size()-1; i++) 
青衫儰鉨ミ守葔 2024-09-21 09:09:40

您已经获得了一些有关如何修复该循环的建议。我的建议是消除它并使用 std::sort 代替。

然而,当我们处理未正确终止的循环时,可能还值得一提的是(在 getEnemies() 中):

    while(!inputFile.eof())
    {
        std::string line;
        inputFile >> line;
        if (line == "<fighter>")
        {
    // ...

这也被破坏了。为了正确终止循环,您需要读取数据,然后检查读取是否成功:

std::string line;

while (inputFile >> line) {
    if (line == "<fighter>") {
         // ...

可能还值得注意的是,这段代码非常脆弱——仅举一个例子,例如: ; 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()):

    while(!inputFile.eof())
    {
        std::string line;
        inputFile >> line;
        if (line == "<fighter>")
        {
    // ...

This is broken as well. For the loop to terminate correctly, you need to read the data, and then check whether the read succeeded:

std::string line;

while (inputFile >> line) {
    if (line == "<fighter>") {
         // ...

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).

夏天碎花小短裙 2024-09-21 09:09:40

尝试将 for 循环更改为这样

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

x[i+1] 永远不会超出范围
您试图访问尚未分配的内存。

Try Changing your for loop to this

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

This way x[i+1] never goes out of bounds
You were trying to access memory that has not been allocated.

诗酒趁年少 2024-09-21 09:09:40

您的问题出在这个循环上:

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() );

Your problem is with this loop:

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
}

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 if i == x.size() then x[i+1] > x.size()

I reccomend changing your loop to terminate at i<(x.size())-1; rather than i<=(x.size());

风蛊 2024-09-21 09:09:40

正如其他人所说,问题在于这一段代码:

    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(含)进行索引。因此,对于基本的向量循环,您应该执行

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

BUT,在下一行代码中,您检查元素 i + 1,因此您应该执行

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

BUT,因为 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::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);

< code>getEnemies、printFightersortFighters 应该是 static 方法,因为它们不需要 的特定实例code>Fighter 进行操作。 (现在,因为它们不是静态方法,所以您必须创建 Fighter 的 enemy 实例才能调用这些方法,即使这些方法都不会对 enemy 执行任何操作code>.)

C++ 允许您在堆栈上创建变量,而不是动态分配它们。换句话说,

Fighter * temp = new Fighter;

而不是仅仅说

Fighter temp;

如果您不需要动态分配,

这更快更简单。最后,C++ 将为您创建复制所有类成员的赋值运算符。因此,您可以简单地编写

temp = x[i];

而不是手动将 x 的每个成员分配给 temp。使用赋值运算符更加可靠,因为如果您稍后将成员添加到 Fighter,它将在将来继续工作。

希望这有帮助。

The problem, as others have said, is this section of code:

    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 can be indexed by values 0 through size() - 1, inclusive. So, for a basic vector loop, you should instead do

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

BUT, in the next line of code, you check element i + 1, so you should instead do

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

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 (like int i against unsigned values (like x.size() - 1) may generate compiler warnings (you should turn all such compiler warnings on, if you haven't already done so), so change i to unsigned or size_t:

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

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 using std::sort:

bool CompareByLevel(const Fighter& a, const Fighter& b) {
    return a.level < b.level;
}

sort(x.begin(), x.end(), CompareByLevel);

Other comments: If you're interested in learning more about C++, here are a few other comments that might help.

inputFile >> line;

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.)

getline(inputFile, line);

getEnemies, printFighter, and sortFighters should be static methods, since they don't need a particular instance of a Fighter to operate on. (Right now, because they're not static methods, you have to create an enemy instance of Fighter in order to call those methods, even though none of those methods do anything with enemy.)

C++ lets you create variables on the stack, instead of dynamically allocating them. In other words, instead of saying

Fighter * temp = new Fighter;

just say

Fighter temp;

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

temp = x[i];

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文