A task involving linked lists and a headache - Page 2
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 2 of 3 FirstFirst 123 LastLast
Results 16 to 30 of 33

Thread: A task involving linked lists and a headache

  1. #16
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Posts
    12,069

    Re: A task involving linked lists and a headache

    I didn't try and compile and run your code, but a quick check still shows this problem that I mentioned previously.
    Code:
    		if(Head==NULL)
    		{
    			InList->Cur=NewBunny;
    			InList->Next=Head; This is wrong
    As to what's wrong with your loop, each time you delete a node, your list gets smaller. Your loop variable i doesn't account for that. You really shouldn't be forcing array constructs onto a list anyway.

    Did you try debugging yet?
    Last edited by GCDEF; October 1st, 2012 at 01:53 PM.

  2. #17
    Join Date
    Apr 1999
    Posts
    27,427

    Re: A task involving linked lists and a headache

    Quote Originally Posted by MustSeeMelons View Post
    Dont have much time, but i have done some changes, created another class that handles the bunnies in the list. The sad parts is that nothing has changed :| If i create 5 bunnies and then delete with a simple cycle (Bold), all is whel, they are deleted, but if i make a cycle with aging (Bold), 2 of them are still not deleted.. Whats wrong with the cycle?
    If your goal is to delete all of the objects, then why not just keep deleting the head object until there are no objects in the list left to delete?
    Code:
    while (there are bunnies in my list)
    {
       delete the head bunny;
    }
    In other words, get rid of the for loop that uses "i". In any event, it's totally wrong anyway. If your list has 6 bunnies, and they are numbered 1,2,3,4,5, and 6, when you delete bunny "1", then bunny 2 now becomes bunny 1, bunny 3 becomes bunny 2, etc... Your for loop implies that when one is deleted, the other bunnies identifying number doesn't decrease. Your loop counter is going up, while the number of bunnies in the list is going down -- see anything wrong with that?

    This is wrong not only in the way you wrote the loop, but the way you implemented the interface to the linked list. You're not supposed to index a linked list like an array, in other words, there is no Bunny[1], Bunny[2], etc.. You can only "point to" or get to a certain item in the list by traversing the list and finding the bunny that you want. So right there, you are not using a linked list in your assignment as a linked list. What you did was write a linked list, and reality using it as if it's an array.

    Secondly, even if you were to use indexing into the list as if it's an array, you're mixing up zero-based and 1-based indexing. Why does Delete use 1 based indexing , but GetBunnyInList uses 0-based indexing? Look at your code -- when you call GetBunnyInList, you immediately subtract 1? The user of your linked list doesn't know whether bunnies start at 0 or 1, given the inconsistency of the implementation. Not only that, your internal code gets confusing with the "Pos-1", "Pos+1", etc. You're practically begging for a memory overwrite or some sort of memory corruption to occur with that type of coding. Be consistent and start at 0, where every C++ programmer expects a container to start indexing.

    Your Add() function is confusing. You're allocating twice for no reason.
    Code:
    int Add(Bunny* NewBunny)
    {
        // create a bunny
        BunnyInList *InList= new BunnyInList;
        InList->Next = NULL;
        if (Head == NULL)
        {
            // this is the head bunny
             Head = InList;
             return ++size;
        }
    
        // there are bunnies already existing, so add this
        // new one to the end of the list
        BunnyInList* Current=Head;
        while(Current->Next)
               Current=Current->Next;
         Current->Next=InList;
         return ++size;
    }
    This is much simpler. If the list is empty, then the new item becomes the head, else you traverse the list and add the new item at the end.

    Regards,

    Paul McKenzie

  3. #18
    Join Date
    Sep 2012
    Posts
    11

    Re: A task involving linked lists and a headache

    Code:
    if(Head==NULL)
    		{
    			InList->Cur=NewBunny;
    			InList->Next=Head; This is wrong
    Head is still NULL at that point, why is it wrong? Should i just use InList=NULL then?
    I tried debugging - it was overwhelming and hard to understand, still searsching for a good debugging tutorial.

    My goal is to make a function, which deletes bunnies when they hit age 10. I was afraid that the list was getting smaller when deleting, thanks for making that clear. Understood, start always with 0, i had some sort of reason why i wrote 1, ill fix that.

    Ok, now i have to ask this, how should i treat i linked list? Use a counter in loops and go through elements by using Next? The reason im trying to use the list like an array is probably because im used to solid structures, the list seems like it could be scattered all over the memory.

    Is there something wrong with using Pos-1 & Pos +1?
    Thank you wery much.

  4. #19
    Join Date
    Apr 1999
    Posts
    27,427

    Re: A task involving linked lists and a headache

    Quote Originally Posted by MustSeeMelons View Post
    Code:
    if(Head==NULL)
    		{
    			InList->Cur=NewBunny;
    			InList->Next=Head; This is wrong
    Head is still NULL at that point, why is it wrong? Should i just use InList=NULL then?
    Just use the implementation of Add() that I had. Your version of Add() complicates everything by making two allocations when one is all that's required.
    I tried debugging - it was overwhelming and hard to understand, still searsching for a good debugging tutorial.
    This is what happens when you copy code from somewhere, and you don't fully understand the code yourself.

    If you wrote the program from scratch, then debugging the program becomes easy because you wrote the program, so you must have had something in mind when you wrote it. In other words, you had a plan, you had this plan written out on paper, and now you implemented it. So now the program doesn't work -- where does the program deviate from the plan you had written down? Then this becomes straightforward as to how to proceed from there.
    The reason im trying to use the list like an array is probably because im used to solid structures, the list seems like it could be scattered all over the memory.
    That's right, and for good reason why the memory is "scattered". When you remove an item from a linked list, all you're doing is manipulating a couple of pointers. If it were a (dynamic) array, you have to remove the item, and then "squeeze" all of the items together in the array to cover up the hole that is created with the item that has been removed. That takes more time to execute.

    Assume you had a linked list of 10,000 items, and you want to delete the 5,000th entry in the list. You have a pointer to the 5,000th entry, so all you need to do is manipulate the pointers to entry 4,999 and 5,001 to remove entry 5000 (and then of course you deallocate the memory for entry 5000). For an array, to delete entry 5,000 requires you to move all the entries starting from 5,001 to cover up the hole created when 5,000 is removed, one by one. That takes way more time, and especially if the entries are expensive to copy.

    In other words, the links in a linked list can be anywhere in memory -- the aspect that keeps them in order is that "Next" pointer link (hence the term "linked list"). For an array, the items must be consecutive in memory. It is the consecutiveness of an array that keeps an array in order (you know where any item is in an array, since each item must follow the previous or next item in memory). Therefore a link in a linked list can be easily removed, since it just needs a couple of pointer updates to remove the item from the list -- it doesn't matter where the link is in memory, as long as the Next pointer is doing the right thing. For an array, to keep the items consecutive, you have to fill the hole created when you removed an item, and that requires copying all elements after the removed item "up by 1".

    Is there something wrong with using Pos-1 & Pos +1?
    There is nothing "wrong", it's just confusing and makes the code harder to maintain. If you had stuck to 0-based indexing, then things become easier.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; October 2nd, 2012 at 10:11 AM.

  5. #20
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Posts
    12,069

    Re: A task involving linked lists and a headache

    Quote Originally Posted by MustSeeMelons View Post
    Code:
    if(Head==NULL)
    		{
    			InList->Cur=NewBunny;
    			InList->Next=Head; This is wrong
    Head is still NULL at that point, why is it wrong? Should i just use InList=NULL then?
    I tried debugging - it was overwhelming and hard to understand, still searsching for a good debugging tutorial.

    My goal is to make a function, which deletes bunnies when they hit age 10. I was afraid that the list was getting smaller when deleting, thanks for making that clear. Understood, start always with 0, i had some sort of reason why i wrote 1, ill fix that.

    Ok, now i have to ask this, how should i treat i linked list? Use a counter in loops and go through elements by using Next? The reason im trying to use the list like an array is probably because im used to solid structures, the list seems like it could be scattered all over the memory.

    Is there something wrong with using Pos-1 & Pos +1?
    Thank you wery much.
    You're right, but as you can see from my mistake, setting next = head and assuming head == NULL makes the code harder to read. If you want it to be NULL, set it to NULL.

    Typically you'll iterate a list using a while loop, checking to see if the current node's next pointer != NULL, although some implementations allow for a for loop also.

  6. #21
    Join Date
    Sep 2012
    Posts
    11

    Re: A task involving linked lists and a headache

    Im happy to inform, that this is a happy post - i corrected my mess and everything is working as it should^^ (Maybe there is a small glitch somewhere, but i havent found it yet). Went through my code and found two really dumb mistakes: GetBunnyInList couldnt return a NULL, so changes were made. And the worst mistake, when deleting a node in the middle i had written that the previous nodes next is the next nodes next, that caused all the deletion problems, dont know what i was thinking when i wrote that line..
    Want to thank GCDEF and esspecially Paul McKenzie for there great posts
    I still have some work to do, like add some more features like:

    ★ Modify the program to run in real time, with each turn lasting 2 seconds, and a one second pause between each announement.

    ★★ Allow the user to hit the 'k' key to initiate a mass rabit cull! which causes half of all the rabits to be killed (randomly chosen).

    ★★★★ Modify the program to place the rabits in an 80x80 grid. Have the rabits move one space each turn randomly.
    Mark juvenile males with m, adult males w/ M,
    juvenile females w/ f, adult femails w/ F
    radioactive mutant vampire bunnies with X

    Modify the program so that radioactive mutant vampire bunnies only convert bunnies that end a turn on an adjacent square.
    Modify the program so that new babies are born in an empty random adjacent square next to the mother bunny. (if no empty square exits then the baby bunny isn't born)

    ★★★★★ Modify the program so that it saves each turn to a file and can play back at accelearted speed all subsequent turns.

    If ill have any more headackes or finish the program with no problems, ill definetly post here.
    Thanks yet again and heres the code, which works.

    Code:
    #include <iostream>
    #include <time.h>
    #include <string>
    
    using namespace std;
    
    char *Names[15]={"Phill","Colin","Bucket","Fluffy","Mister","Lilly","Rose","Shamandale","Yoshie","Jane","PeanutButter","Plank","Sucubus","Broken","Horse ****"};
    class Bunny
    {
    public:
    	string Sex;
    	string Color;
    	int Age;
    	string Name;
    	bool Mutant;
    
    	Bunny *Next;
    
    	int Random(int x)
    	{
    		return x=rand()%(x+1);
    	}
    	
    	bool MutantBunny()
    	{
    		int X=Random(100);
    		if(X<1)
    		{
    			return true;
    		}
    		return false;
    	}
    
    	string SexIsNotAChoise()
    	{
    		int R=Random(10);
    		if(R<5)
    		{
    			Sex="Male";
    		}
    		else
    		{
    			Sex="Female";
    		}
    		return Sex;
    	}
    
    	string HopeImNotBlack()
    	{
    		int R=Random(100);
    		if(R<24)
    		{
    			Color="White";
    		}
    		else if(R>24 && R<=49)
    		{
    			Color="Brown";
    		}
    		else if(R>50 && R<=75)
    		{
    			Color="Black";
    		}
    		else if(R>76)
    		{
    			Color="Spotted";
    		}
    		return Color;
    	}
    
    	int ImNotOld()
    	{
    		Age=0;
    		return Age;
    	}
    
    	string HelloMyNameIs()
    	{
    		if(Mutant==true)
    		{
    			Name=Names[rand()%(14-10)+10];
    		}
    		else if(Sex=="Male")
    		{
    			Name=Names[rand()%5];
    		}
    		else if(Sex=="Female")
    		{
    			Name=Names[rand()%(9-5)+5];
    		}
    		return Name;
    	}
    
    	Bunny()
    	{
    		Mutant=MutantBunny();
    		if(Mutant==true)
    		{
    			Sex=SexIsNotAChoise();
    			Color="Green";
    			Age=ImNotOld();
    			Name=HelloMyNameIs();
    		}
    		else if(Mutant==false)
    		{
    			Sex=SexIsNotAChoise();
    			Color=HopeImNotBlack();
    			Age=ImNotOld();
    			Name=HelloMyNameIs();
    		}
    		
    	}
    
    	void print()
    	{
    		cout<<"Bunny "<<Name<<" was born!";
    		if(Mutant==true)
    		{
    			cout<<" He's a mutant..!"<<endl;
    		}
    		else
    		{
    			cout<<endl;
    		}
    	}
    
    	~Bunny()
    	{
    		cout<<"A bunny with the name "<<Name<<" has died!"<<endl;
    	}
    
    };
    
    class BunnyInList
    	{
    	public:
    		BunnyInList *Next;
    		Bunny *Cur;
    	};
    
    class BunnyList
    {
    public:
    	
    	BunnyInList *Head;
    	int size;
    	int BunnyCount;
    
    	BunnyList()
    	{
    		Head=NULL;
    		size=0;
    		BunnyCount=0;
    	}
    
    	int Count()
    	{
    		return size;
    	}
    
    	int Add(Bunny* NewBunny)
    	{
    		BunnyInList *InList= new BunnyInList;
    		InList->Next=NULL;
    		if(Head==NULL)
    		{
    			InList->Cur=NewBunny;
    			Head=InList;
    			BunnyCount++;
    			return ++size;
    		}
    		else
    		{
    			BunnyInList *Current=Head;
    			while(Current->Next!=NULL)
    			{
    				Current=Current->Next;
    			}
    			Current->Next=InList;
    			InList->Cur=NewBunny;
    			BunnyCount++;
    			return ++size;
    			
    		}
    	}
    
    	BunnyInList *GetBunnyInList(int Pos)
    	{
    		BunnyInList *Current=Head;
    		if(Pos>=0)
    		{
    			for(int i=0;i<Pos && Current!=NULL;i++)
    			{
    				Current=Current->Next;
    			}
    			return Current;
    		}
    		else
    		{
    			return Current=NULL;
    		}
    		
    	}
    
    	bool Delete(int Pos)
    	{
    		if(GetBunnyInList(Pos-1)==NULL)
    		{
    			Head=GetBunnyInList(Pos+1);
    			size--;
    			return true;
    		}
    		else if(GetBunnyInList(Pos+1)==NULL)
    		{
    			GetBunnyInList(Pos-1)->Next=NULL;
    			size--;
    			return true;
    		}
    		else
    		{
    			GetBunnyInList(Pos-1)->Next=GetBunnyInList(Pos+1);
    			size--;
    			return true;
    		}
    		return false;
    	}
    
    	int MutantCheck()
    	{
    		int MutantCount=0;
    		for(int i=0;i<Count() && GetBunnyInList(i)!=NULL;i++)
    		{
    			if(GetBunnyInList(i)->Cur->Mutant==true)
    			{
    				MutantCount++;
    			}
    		}
    		return MutantCount;
    	}
    
    	int NormalCheck()
    	{
    		int NormalCount=0;
    		for(int i=0;i<Count() && GetBunnyInList(i)!=NULL;i++)
    		{
    			if(GetBunnyInList(i)->Cur->Mutant==false)
    			{
    				NormalCount++;
    			}
    		}
    		return NormalCount;
    	}
    
    	int Male()
    	{
    		int M=0;
    		for(int i=0;i<Count() && GetBunnyInList(i)!=NULL;i++)
    		{
    			if(GetBunnyInList(i)->Cur->Sex=="Male" && GetBunnyInList(i)->Cur->Age>2 && GetBunnyInList(i)->Cur->Mutant==false)
    			{
    				M++;
    			}
    		}
    		return M;
    	}
    
    	int Female()
    	{
    		int F=0;
    		for(int i=0;i<Count() && GetBunnyInList(i)!=NULL;i++)
    		{
    			if(GetBunnyInList(i)->Cur->Sex=="Female" && GetBunnyInList(i)->Cur->Age>2 && GetBunnyInList(i)->Cur->Mutant==false)
    			{
    				F++;
    			}
    		}
    		return F;
    	}
    
    	bool WeWillMate()
    	{
    		int M=Male(),F=Female();
    		if(M>=1 && F>=1)
    		{
    			return true;
    		}
    		else
    		{
    			return false;
    		}
    	}
    
    	void OutOfFood()
    	{
    		if(Count()>1000)
    		{
    			int ToKill=Count()/2;
    			while(ToKill!=0)
    			{
    				int UnLucky=rand()%(Count());
    				BunnyInList *Temp=GetBunnyInList(UnLucky);
    				Delete(UnLucky);
    				delete Temp->Cur;
    				ToKill--;
    			}
    		}
    	}
    
    	void Conversion()
    	{
    		int Change=MutantCheck();
    		int Normal=NormalCheck();
    		if(Change>0 && Normal>0)
    		{
    			while(Change!=0)
    			{
    				int UnLucky=rand()%(Count());
    				BunnyInList *Temp=GetBunnyInList(UnLucky);
    
    				while(GetBunnyInList(UnLucky)->Cur->Mutant!=false)
    				{
    					UnLucky=rand()%(Count());
    				}
    				Temp=GetBunnyInList(UnLucky);
    					
    				Temp->Cur->Mutant=true;
    				Temp->Cur->Color="Green";
    				cout<<Temp->Cur->Name<<" is a mutant now!"<<endl;
    				Change--;
    				Normal--;
    				if(Normal==0)
    				{
    					break;
    				}
    				
    			}
    		}
    		
    	}
    
    };
    
    void PrintTheHorde(BunnyList* List)
    {
    		cout<<"The Horde consists of "<<List->Count()<<" bunnies, here they are: "<<endl;
    		cout<<endl;
    		for(int i=0;i<List->Count() && List->GetBunnyInList(i)!=NULL;i++)
    		{
    				BunnyInList *Temp=List->GetBunnyInList(i);
    				cout<<"Name: "<<Temp->Cur->Name<<" Sex: "<<Temp->Cur->Sex<<" Age: "<<Temp->Cur->Age<<" Color: "<<Temp->Cur->Color;
    				if((Temp->Cur->Mutant)==true)
    				{
    					cout<<" Im a Mutant.."<<endl;
    				}
    				else if((Temp->Cur->Mutant)==false)
    				{
    					cout<<endl;
    				}
    		}
    }
    
    int main()
    {
    	srand(time(NULL));
    	BunnyList *List=new BunnyList;
    	for(int i=0;i<5;i++)
    	{
    		Bunny *NewBunny=new Bunny();
    		List->Add(NewBunny);
    		NewBunny->print();
    	}
    
    	while(List->Count()>0)
    	{
    		int i=0;
    		BunnyInList *Temp=List->Head;
    		while(Temp!=NULL)
    		{
    			Temp->Cur->Age++;
    			if(Temp->Cur->Mutant==true)
    				{
    					if(Temp->Cur->Age==50)
    					{
    						List->Delete(i);
    						delete Temp->Cur;
    						i--;
    					}
    				}
    			else if(Temp->Cur->Mutant==false)
    			{
    				if(Temp->Cur->Age==10)
    				{
    					List->Delete(i);
    					delete Temp->Cur;
    					i--;
    				}
    			
    			}
    			Temp=Temp->Next;
    			i++;
    		}
    
    		bool Mate=List->WeWillMate();
    		if(Mate==true)
    		{
    			int NewB=List->Female();
    			for(int i=0;i<NewB;i++)
    			{
    				Bunny *NewBunny=new Bunny();
    				List->Add(NewBunny);
    				NewBunny->print();
    			}
    		}
    		List->Conversion();
    		List->OutOfFood();
    
    		int m=List->Male(),f=List->Female();
    		cout<<"Adult males: "<<m<<endl;
    		cout<<"Adult females: "<<f<<endl;
    		cout<<"The Horde consists of "<<List->Count()<<" bunnies! "<<endl;
    		//system("pause");
    		//system("cls");
    		/*system("pause");
    		system("cls");*/
    	}
    	
    	cout<<endl;
    	cout<<"A total of "<<List->BunnyCount<<" bunnies lived in this farm.."<<endl;
    	
    	return getchar();
    }

  7. #22
    Join Date
    Jan 2009
    Posts
    596

    Re: A task involving linked lists and a headache

    Code:
    string HopeImNotBlack()
    	{
    		int R=Random(100);
    		if(R<24)
    		{
    			Color="White";
    		}
    		else if(R>24 && R<=49)
    		{
    			Color="Brown";
    		}
    		else if(R>50 && R<=75)
    		{
    			Color="Black";
    		}
    		else if(R>76)
    		{
    			Color="Spotted";
    		}
    		return Color;
    	}
    This must be a first - I've never seen a racist method name before

  8. #23
    Join Date
    Sep 2012
    Posts
    11

    Re: A task involving linked lists and a headache

    Quote Originally Posted by Peter_B View Post
    This must be a first - I've never seen a racist method name before
    Well thank you. Im not racist, but i do like to make my method names a bit more interesting, otherwise its just too plain and booring, without any character. Spices thing up.

  9. #24
    Join Date
    Jan 2009
    Posts
    596

    Re: A task involving linked lists and a headache

    Quote Originally Posted by MustSeeMelons View Post
    Well thank you. Im not racist, but i do like to make my method names a bit more interesting, otherwise its just too plain and booring, without any character. Spices thing up.
    I didn't say you were racist, I said the method name was
    But seriously, you should consider how the person marking this assignment might see this. They won't be looking for 'interesting' method names, but would prefer that they are clear and descriptive of what the method does.

    The place to spice things up is in the user interface, not the code.

  10. #25
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Posts
    12,069

    Re: A task involving linked lists and a headache

    You have a number of issues with your code that could be improved.

    You need to get the next pointer out of your Bunny Class.

    Your use of Random makes little sense. You're doing weird things like saying Random(10) to determine sex, when it seems like Random(2) would make more sense. Same with color.

    You'd be better off storing attributes as ordinal values rather than string literals. Then you could do things like
    sex = Random(2);
    without all those if statements. If you use enums or const ints rather than string literals, the compiler will catch it if you make a spelling mistake, whereas it won't with string literals.

    What's the difference between size and BunnyCount in your list?

    Why are you writing things like
    Name=Names[rand()%(14-10)+10
    Why not just write 4 if you mean 4?

    If you maintained a pointer to the tail of your list, you wouldn't have to iterate the list every time you add a bunny.

    There are other issues but if you're so inclined, you could start with them.
    Last edited by GCDEF; October 4th, 2012 at 07:33 AM.

  11. #26
    Join Date
    Sep 2012
    Posts
    11

    Re: A task involving linked lists and a headache

    Um, the Bunny doesnt have the next pointer, BunnyInList does, the Bunny it self has no idea that its in a class.
    As for the Random function, well, youre right, dont know how i didnt think of that before, thanks.
    The BunnyCount is just a ticker on how many bunnies have lived in total, its not decremented, as for now, 2547 is the biggest farm ive had

    Why are you writing things like
    Name=Names[rand()%(14-10)+10
    Why not just write 4 if you mean 4?

    Because the Names array contains all gender & mutant names, so i need a random number between 10 and 14 for specific names, i might just make 3 different arrays if ill want to add more names.
    The code runs great, so for now ill keep it as it is and will take your advice the next time ill be making something simiral.

    Noone is marking this, its just for myself, the code is just for me. I would like the code to be a bit spiced, so that i can think odd things about people based on there code

    A question about programming itself, ill be graduating next year and i am willing to learn usefull programming related stuff at home. For now im doing C++ and JAVA, what else could be usefull? To try to land a job or practise position?

    Last question, related to the real-time program execution.

    "Modify the program to run in real time, with each turn lasting 2 seconds, and a one second pause between each announement."

    How to understand the bolded part? I have to restrict the time given for the turn or make a pause? Ive made a function which takes care of the pause.

    Code:
    void TimePause(int MiliS)
    {
    	int Time=clock();
    	while(Time+MiliS!=clock());
    }

  12. #27
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Posts
    12,069

    Re: A task involving linked lists and a headache

    Look at your Bunny class again. The most recent one still has a next*.

    Still, why write (14 - 10) instead of just 4?

  13. #28
    Join Date
    Apr 1999
    Posts
    27,427

    Re: A task involving linked lists and a headache

    Noone is marking this, its just for myself, the code is just for me.
    So why didn't you just use the std::list class?
    The code runs great, so for now ill keep it as it is
    The issue is not that it "runs great" (and that isn't even conclusive). The issue is that you don't want to write code in the way you wrote it. It is not the way a junior or senior professional programmer would write the code. For example, your BunnyList lacks a proper copy constructor and assignment operator. I can crash or totally make your class useless with just a 2 or 3 line main() program. Another example is that you don't check what happens if the color is exactly 24.

    Another example is this:
    Code:
    GetBunny(z)->~Bunny();
    This is not how you use destructors. By doing this, your object is erroneously destroyed twice, once with that ill-advised line above, and another when the object goes out of scope.

    Honestly, don't keep this program. It has bugs, bad coding, etc.
    A question about programming itself, ill be graduating next year and i am willing to learn usefull programming related stuff at home.
    Learn how to use the C++ library. There already is a std::list class that you could/should have used. Unless you know how to use the standard library, you really can't call yourself a C++ programmer to any great extent.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; October 7th, 2012 at 08:25 PM.

  14. #29
    Join Date
    Apr 1999
    Posts
    27,427

    Re: A task involving linked lists and a headache

    Here is an example of usage of the standard library. Note how many of your functions have been eliminated, replaced with library functions.
    Code:
    #include <iostream>
    #include <list>
    #include <string>
    #include <algorithm>
    #include <time.h>
    
    using namespace std;
    
    const char *Names[]={"Phill","Colin","Bucket","Fluffy","Mister","Lilly","Rose","Shamandale","Yoshie","Jane","PeanutButter","Plank","Sucubus","Broken","Horse ****"};
    
    class Bunny
    {
        string Gender;
        string Color;
        int Age;
        string Name;
        bool Mutant;
        
    public:
        std::string GetName() const { return Name; }
        std::string GetColor() const { return Color; }
        int  GetAge() const { return Age; }
        void SetAge(int theAge) { Age = theAge; }
        std::string GetGender() const { return Gender; }
        bool IsMutant() const { return Mutant; }
        bool IsMale() const { return Gender == "Male" && Age > 2; }
        bool IsFemale() const { return Gender == "Female" && Age > 2; }
        bool IsOlderInAge(int testAge) const { return Age > testAge; }
        bool IsYoungerInAge(int testAge) const { return Age < testAge; }
        bool IsEqualInAge(int testAge) const { return Age == testAge; }
       
        int Random(int x)
        { return x=rand()%(x+1); }
    
        bool MutantBunny()
        {
            int X=Random(100);
            return X < 2;
        }
    
        string SetGender()
        {
            int R=Random(10);
            Gender = (R<5?"Male":"Female");
            return Gender;
        }
    
        string SetColor()
        {
            int R=Random(100);
            if(R<24)
                Color="White";
            else if(R>24 && R<=49)
                Color="Brown";
            else if(R>50 && R<=75)
                Color="Black";
            else if(R>76)
                Color="Spotted";
            return Color;
        }
    
        int ResetAge()
        {
            Age=0;
            return Age;
        }
    
        std::string SetName()
        {
            if(Mutant)
            {
                Name=Names[rand()%(14-10)+10];
            }
            else if(Gender=="Male")
            {
                Name=Names[rand()%5];
            }
            else if(Gender=="Female")
            {
                Name=Names[rand()%(9-5)+5];
            }
            return Name;
        }
    
        Bunny()
        {
            Mutant=MutantBunny();
            if(Mutant)
            {
                Gender=SetGender();
                Color="Green";
                Age=ResetAge();
                Name=SetName();
            }
            else 
            {
                Gender=SetGender();
                Color=SetColor();
                Age=ResetAge();
                Name=SetName();
            }
    
        }
    
        void print()
        {
            std::cout<<"Bunny "<<Name<<" was born!";
            if (Mutant)
            {
                cout<<" He's a mutant..!"<<endl;
            }
            else
            {
                cout<<endl;
            }
        }
    
        ~Bunny()
        {
            cout<<"A bunny with the name "<<Name<<" has died!"<<endl;
        }
    };
    
    class BunnyList
    {
        typedef std::list<Bunny> BunnyLinkedList;
        private:
            BunnyLinkedList m_theBunnyList;
            
        public:
            typedef enum {AGE_EQUAL, AGE_YOUNGER, AGE_OLDER } AgeType;
            int Count()
            { return (int)m_theBunnyList.size(); }
    
            void AddBunny(const Bunny& NewBunny)
            { m_theBunnyList.push_back(NewBunny); }
    
            const Bunny& GetBunny(int Pos) const 
            {
                if ( Pos >= 0 && Pos < (int)m_theBunnyList.size())
                {
                   BunnyLinkedList::const_iterator it = m_theBunnyList.begin();
                   std::advance(it, Pos);
                   return *it;
                }
                throw std::out_of_range("Bunny position invalid");
            }
    
            bool Delete(int Pos)
            {
                if ( Pos >= 0 && Pos < (int)m_theBunnyList.size())
                {
                    BunnyLinkedList::const_iterator it = m_theBunnyList.begin();
                    std::advance(it, Pos);
                    m_theBunnyList.erase(it);
                    return true;
                }
                return false;
            }
    
            int GetNumMutants()
            { return (int)std::count_if(m_theBunnyList.begin(), m_theBunnyList.end(), std::mem_fun_ref(&Bunny::IsMutant)); }
    
            int GetNumMale()
            { return (int)std::count_if(m_theBunnyList.begin(), m_theBunnyList.end(), std::mem_fun_ref(&Bunny::IsMale)); }
    
            int GetNumFemale()
            { return (int)std::count_if(m_theBunnyList.begin(), m_theBunnyList.end(), std::mem_fun_ref(&Bunny::IsFemale)); }
    
            bool WeWillMate()
            {
                int M=GetNumMale();
                int F=GetNumFemale();
                return (M>=1 && F>=1);
            }
    
            void OutOfFood()
            {
                if(Count()>100)
                {
                    int k=Count()/2;
                    for(int i=0;i<k;i++)
                    {
                        int z=rand()%k;
                        Delete(z);
                    }
                }
            }
            
            void PrintAllBunnies() const 
            {
                cout<<"The Horde consists of " << m_theBunnyList.size() <<" bunnies, here they are: "<<endl;
                cout<<endl;
                BunnyLinkedList::const_iterator it = m_theBunnyList.begin();
                while (it != m_theBunnyList.end())
                {
                    const Bunny& Temp = *it;
                    cout<<"Name: "<<Temp.GetName() <<" Sex: "<<Temp.GetGender() <<" Age: "<<Temp.GetAge() <<" Color: "<<Temp.GetColor();
                    if (Temp.IsMutant())
                        cout<<" Im a Mutant.."<<endl;
                    else
                        cout<<endl;
                    ++it;
                }
            }
            
            void DeleteByAge(int age, AgeType aType = AGE_EQUAL)
            {
                switch (aType)
                {
                    case AGE_EQUAL:
                        m_theBunnyList.remove_if(std::bind2nd(std::mem_fun_ref(&Bunny::IsEqualInAge), age));
                    break;                    
                    case AGE_YOUNGER:
                        m_theBunnyList.remove_if(std::bind2nd(std::mem_fun_ref(&Bunny::IsYoungerInAge), age));
                    break;                    
                    case AGE_OLDER:
                        m_theBunnyList.remove_if(std::bind2nd(std::mem_fun_ref(&Bunny::IsOlderInAge), age));
                    break;                    
                }
            }
    };
    
    int main()
    {
        srand(time(NULL));
        BunnyList List;
    
        for(int i=0;i<5;i++)
        {
            Bunny theBunny; 
            List.AddBunny(theBunny);
            theBunny.print();
        }
    
        // remove all bunnies with age 10
        List.DeleteByAge( 10 );
        List.PrintAllBunnies();
        return getchar();
    }
    To be honest, this isn't even my best attempt. I didn't address the random number issues that GCDEF mentioned, but at the very least, you can start to look at this code and understand how it does what it does.

    Regards,

    Paul McKenzie

  15. #30
    Join Date
    Sep 2012
    Posts
    11

    Re: A task involving linked lists and a headache

    Look at your Bunny class again. The most recent one still has a next*.

    Still, why write (14 - 10) instead of just 4?
    Forgot to delete that pointer for the bunny, anyway, it wasnt used.
    Because, rand()%4 would give me 0-4, but those positions contain Male names, i need rand()%(14 - 10)+10 gives me 10-14, which are the names i need.

    So why didn't you just use the std::list class?
    I had C++ just for 1 semester, one in two weeks, we didnt have classes what so ever, mostly just OOP principles etc.,
    So I took the hard road. The upside is that i feel that i have learned something.

    Learn how to use the C++ library. There already is a std::list class that you could/should have used. Unless you know how to use the standard library, you really can't call yourself a C++ programmer to any great extent.
    Im not saying i am, i am willing to be. Ok then, will look in to your code and start learning STL.I got 8 months to make myself usefull, wish me luck

Page 2 of 3 FirstFirst 123 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Azure Activities Information Page

Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center