C++ 做一个关于兔子殖民地的练习,撞墙

C++ 做一个关于兔子殖民地的练习,撞墙,c++,linked-list,C++,Linked List,我在做这个清单上的最后一个练习(它叫毕业):但有一个主要问题。我编写的代码可以运行,但它会在此时崩溃(在删除半个bunnie之后),有时在程序第一次删除半个bunnie之后,有时在10个这样的周期之后,请注意,我还没有实现很多,因为我想在您的帮助下修复这个bug。我也知道这不是代码审查,但是一些关于风格和改进的小技巧也会很好。这是我到目前为止写的代码: Main.cpp: include bunnyList.h include windows.h using namespace std; i

我在做这个清单上的最后一个练习(它叫毕业):但有一个主要问题。我编写的代码可以运行,但它会在此时崩溃(在删除半个bunnie之后),有时在程序第一次删除半个bunnie之后,有时在10个这样的周期之后,请注意,我还没有实现很多,因为我想在您的帮助下修复这个bug。我也知道这不是代码审查,但是一些关于风格和改进的小技巧也会很好。这是我到目前为止写的代码:

Main.cpp:

include bunnyList.h
include windows.h

using namespace std;

int main(){
    srand(time(NULL));
    bunnyList Colony;
    int turns = 0;
    Colony.setUp();
    while(Colony.getColonySize() > 0){
        //New turn
        Colony.increaseAgeAndKill();
        Colony.breedBunnies();

        std::cout << "Turn: "<< turns << ". Colony size: " << Colony.getColonySize() << std::endl;
        //Get rid of these food eaters
        if(Colony.getColonySize() > 1000){
        std::cout << "500 bunnies died!" << std::endl;
        Colony.killHalfBunnies();
        }
    Sleep(100);
    turns++;;
    }
}
包括bunnyList.h
包括windows.h
使用名称空间std;
int main(){
srand(时间(空));
兔群;
整数匝数=0;
Colony.setUp();
while(Colony.getColonySize()>0){
//新一轮
Colony.increaseandkill();
殖民地。布里德布尼();
std::cout isMale);
兔子->年龄=0;
bunny->next=NULL;
兔子->可繁殖=0;
if(head==NULL){
头=兔子;
返回;
}
while(临时->下一步!=NULL){
温度=温度->下一步;
}
温度->下一步=兔子;
noOfBunnies++;
}
void bunnyList::increaseAgeAndKill(){
电流=水头;
prev=头部;
while(当前!=NULL){
当前->年龄++;
//检查兔子是否能繁殖
如果(当前->年龄>2){
当前->可繁殖=1;
}
//检查是否到了死亡时间:/
如果(当前->年龄>10){
deleteNode();
}
prev=当前值;
当前=当前->下一步;
}
电流=水头;
prev=头部;
}
void bunnyList::breedBunnies(){
节点*温度=头部;
bool-oneMale=0;
int femalecont=0;
//检查是否至少有一只可繁殖雄性
while(temp!=NULL){
如果(临时->isMale&&temp->可繁殖){
一男=1;
打破
}
温度=温度->下一步;
}
//每只2岁以上的雌性兔子都会出生一只新的兔子
温度=水头;
if(一名男性){
while(temp!=NULL){
如果(temp->isMale==0&&temp->isBreedable){
纽班尼(温度->颜色);
}
温度=温度->下一步;
}
}
}
void bunnyList::deleteNode(){
如果(当前==水头){
头部=当前->下一步;
prev=头部;
删除当前文件;
电流=水头;
努夫布尼——;
}else if(当前->下一步==NULL){
删除当前文件;
prev->next=NULL;
prev=头部;
电流=水头;
努夫布尼——;
}否则{
上一个->下一个=当前->下一个;
当前->下一步=空;
删除当前文件;
当前=上一个->下一个;
努夫布尼——;
}
}
std::string bunnyList::getRandomName(bool isMale){
int r=getRandomNumber(numf名称-1);
如果(isMale)
返回maleNames[r];
返回femaleNames[r];
}
std::string bunnyList::getRandomColor(){
int r=getRandomNumber(numOfColors-1);
返回颜色[r];
}
bool bunnyList::isMaleRandom(){
如果(getRandomNumber(2)==1){return true;}
返回false;
}
int bunnyList::getRandomNumber(int limit)常量{
返回rand()%limit+1;
}
int bunnyList::getColonySize()常量{
返回noOfBunnies;
}
节点h:

#ifndef NODE_H_INCLUDED
#define NODE_H_INCLUDED

#include <string>

class node {
    friend class bunnyList;
private:
    std::string name;
    int age;
    std::string color;
    bool isMale;
    node *next;
    bool isBreedable;
public:
};

#endif // NODE_H_INCLUDED
#如果包含节点#
#定义包含的节点
#包括
类节点{
朋友班兔女郎;
私人:
std::字符串名;
智力年龄;
字符串颜色;
布尔伊斯梅尔;
节点*下一步;
布尔是可繁殖的;
公众:
};
#endif//NODE_H_包括在内

谢谢你的帮助。

既然你要求复习

永远不要使用命名空间std编写
。永远不要。就在今天早上,有人问了一个问题,问题的原因是那句臭名昭著的话。我想知道是谁和为什么建议这是一个好方法-应该有一本这样的书。如果我有我的方式,它的作者将被判永远手动删除从每个文件中删除这一行

即使不阅读代码中的任何一行,仅通过解释,我知道问题最有可能(100%可能,如中所示)与内存管理相关。您正在释放未正确分配的内存,您正在释放两次相同的内存,或者您正在释放一些根本没有分配的内存,或者您正在访问释放后的内存。查看您的
删除
并检查它们

在样式上。您的代码基本上是业务逻辑感知列表的实现。一般来说,这不是一个好的实践。最好实现一个通用列表,支持添加、删除和其他通用列表操作,而不是在此通用列表之上实现您的业务逻辑

不要在列表中使用
current
。而是在delete函数中传递要删除的节点

最后,在调试器中运行程序并查看要删除的变量

编辑 用逗号回答问题

这就是我所说的业务逻辑分离。有一种通用的数据结构,称为list。它可以是任何东西的列表,兔子或太空火箭,没关系,但它仍然支持基本的列表操作。显然,最重要的两个操作是insert和delete,但它不是通用列表的唯一操作。您可以阅读wikipedia列表(数据结构)对于一般想法,请查看std::list作为实现。现在,您有了list的特定用例,一个兔子列表。对于特定用例,您将在通用列表上添加功能。为了进一步澄清,从列表中删除项目是通用列表支持的。但是当可怜的动物10岁时,“杀死兔子”年是业务逻辑的一部分。它包含对兔子列表的迭代(由通用列表提供)、检查年龄和做出消除该生物的决定(业务逻辑级别)以及删除元素(通用列表)。如果使用
std::list
编写此代码,它将
#include "bunnyList.h"

bunnyList::bunnyList(){
        noOfBunnies = 0;
}

void bunnyList::setUp(){
        std::string temp = "";
        head = NULL;
        for(int i = 0; i <= bunniesIni; i++){
            newBunny(temp);
        }
}

void bunnyList::killHalfBunnies(){
    prev = head;
    current = head;

    while(noOfBunnies > 500){
        if(getRandomNumber(2) == 1){
            deleteNode();
            continue;
        } else if(current == NULL){
            current = head;
            prev = head;
       } else {
            prev = current;
            current = current->next;
            continue;
        }

    }
}

void bunnyList::newBunny(std::string color){
    node *bunny = new node();
    node *temp = head;

    if(color == ""){
        bunny->color = getRandomColor();
    } else {
        bunny->color = color;
    }

    bunny->isMale = isMaleRandom();
    bunny->name = getRandomName(bunny->isMale);
    bunny->age = 0;
    bunny->next = NULL;
    bunny->isBreedable = 0;

    if(head == NULL){
        head = bunny;
        return;
    }

    while(temp->next != NULL){
        temp = temp->next;
    }

    temp->next = bunny;
    noOfBunnies++;
}

void bunnyList::increaseAgeAndKill(){
    current = head;
    prev = head;
    while(current != NULL){
        current->age++;
        //Check if bunny can breed
        if(current->age > 2){
            current->isBreedable = 1;
        }
        //Check if its time to die :/
        if(current->age > 10){
            deleteNode();
        }
        prev = current;
        current = current->next;
    }
    current = head;
    prev = head;
}

void bunnyList::breedBunnies(){
    node *temp = head;
    bool oneMale = 0;
    int femaleCount = 0;
    //Check if there is at least one breedable male
    while(temp!=NULL){
        if(temp->isMale && temp->isBreedable){
            oneMale = 1;
            break;
        }
        temp = temp->next;
    }
    //For every female bunny over 2 years old a new bunny is born
    temp = head;
    if(oneMale){
    while(temp != NULL){
            if(temp->isMale == 0 && temp->isBreedable){
                newBunny(temp->color);
            }
        temp = temp->next;
        }
    }
}

void bunnyList::deleteNode(){
    if(current==head){
        head = current->next;
        prev = head;
        delete current;
        current = head;
        noOfBunnies--;
    } else if(current->next==NULL){
        delete current;
        prev->next = NULL;
        prev = head;
        current = head;
        noOfBunnies--;
    } else {
        prev->next = current->next;
        current->next = NULL;
        delete current;
        current = prev->next;
        noOfBunnies--;
    }
}

std::string bunnyList::getRandomName(bool isMale){
    int r = getRandomNumber(numOfNames - 1);
    if(isMale)
    return maleNames[r];
    return femaleNames[r];
}

std::string bunnyList::getRandomColor(){
    int r = getRandomNumber(numOfColors - 1);
    return colors[r];
}

bool bunnyList::isMaleRandom(){
    if(getRandomNumber(2) == 1) {return true;}
    return false;
}

int bunnyList::getRandomNumber(int limit) const{
    return rand() % limit + 1;
}

int bunnyList::getColonySize() const{
    return noOfBunnies;
}
#ifndef NODE_H_INCLUDED
#define NODE_H_INCLUDED

#include <string>

class node {
    friend class bunnyList;
private:
    std::string name;
    int age;
    std::string color;
    bool isMale;
    node *next;
    bool isBreedable;
public:
};

#endif // NODE_H_INCLUDED
std::list<Bunny> bunnies;
for (auto bunny = bunnies.cbegin(), end = bunnies.cend(); bunny != end; ++bunny) {
    if (bunny->age() > 10)
        bunny = bunnies.erase(bunny);
}
    if (getRandomNumber(2) == 1){
        deleteNode();
        continue;
    }
    else if (current == NULL){
        current = head;
        prev = head;
    }
    if (current == NULL)
    {
        current = head;
        prev = head;
    }
    else if (getRandomNumber(2) == 1)
    {
        deleteNode();
        continue;
    }