Thread: Dynamic memory in C

  1. #16
    Registered User
    Join Date
    Mar 2011
    Location
    Windsor, Ontario
    Posts
    44
    Yea, I wasn't sure about the allocation thing either, is it best to just use malloc() before the while loop? And I guess it was easy to make global, probably not the best but I think global works.

  2. #17
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by JamesD View Post
    Yea, I wasn't sure about the allocation thing either, is it best to just use malloc() before the while loop? And I guess it was easy to make global, probably not the best but I think global works.
    Your malloc calls should be made inside the functions where you are adding new items...

    Global variables are bad in all kinds of ways... Not just the example you just gave yourself.

  3. #18
    Registered User
    Join Date
    Mar 2011
    Location
    Windsor, Ontario
    Posts
    44
    In this case, the only function I see that needs malloc() is the InputRecord function, I took temp out of global and added that to ResetList and changed from using if to switch statements in main. To give an update on what my whole code looks like now this is it:
    Code:
    #include <stdlib.h>
    #include <stdio.h>
    
    struct point
    {
    	int x; //point x
    	int y; //point y
    	char label[21]; //label of 2 points
    	struct point *ptrNext;	// self referential pointer
    };
    
    struct point *ptrFirst = NULL;
    struct point *ptrLast = NULL;
    struct point *ptrNew = NULL;
    
    int isEmptyList(struct point *ptrF);
    void PrintList(struct point *ptrF);
    void ResetList(struct point *ptrF, struct point *ptrL);
    void AddToBeginning(struct point *ptrF, struct point *ptrL);
    void AddToEnd(struct point *ptrF, struct point *ptrL);
    void InputRecord(struct point *ptrNew); // used by Add to interactively get the values from the user
    int isEmptyList(struct point *ptrF)//emptylist will determine if the list is empty
    {
       {
    		if(ptrF==NULL)
    		{
    			return 0;
    		}
    		else
    			return 1;
       }
    }
    //print list will print out everything
    void PrintList(struct point *ptrF)
    {
    	struct point *pC = ptrF;
    	while(pC != NULL)
       {
    		printf("Label: %s\nx: %d y:%d\n", pC->label, pC->x, pC->y);
    		pC = pC->ptrNext;  // this is how a list is traversed
       }	
    }
    //reset list will make everything equal to NULL
    void ResetList(struct point *ptrF, struct point *ptrL)
    {
    	struct point *temp=NULL;
    	while(ptrF!=NULL)
    	{
    		temp=ptrF->ptrNext;
    		free(ptrF);
    		ptrF=temp;
    	}
    }
    //addtobeginning will add a number to the beginning
    void AddToBeginning(struct point *ptrF, struct point *ptrL)
    {
    	if(ptrF==NULL)
             ptrF=ptrNew;
    	InputRecord(ptrNew);
    	ptrFirst->ptrNext=NULL;
    }
    //addtoend will add a number to the end
    void AddToEnd(struct point *ptrF, struct point *ptrL)
    {
    	if(ptrF==NULL)
    		ptrF = ptrNew;
    	else
    	{
    		InputRecord(ptrNew);
    		ptrL=ptrNew;
    	}	
    }
    //reads in input
    void InputRecord(struct point *ptrNew)
    {
    	ptrNew=(struct point *)(malloc(sizeof(struct point)));
    	printf("Please enter the 2 Data points(x and y):\n");
    	ptrFirst=ptrNew;
    	if(ptrNew==NULL)
    		printf("No more memory.\n");
    	else
    	{
    		scanf("%d%d",&ptrFirst->x, &ptrFirst->y);	
    		printf("Please enter the label:\n");
    		scanf("%s", ptrFirst->label);
    	}
    }
    
    void main()
    {
    	int empty=0;//helps determine if list is empty
    	int input=1;//reads in user input
    	while(input!=0)
    	{
    		printf(
    		"1. Add a point at the END of the list.\n"
    		"2. Add a point at the BEGINNING of the list.\n"
    		"3. Is the list empty?\n"
    		"4. Erase all points from the list (reset).\n"
    		"5. Display the list.\n"
    		"6. Save the list to a sequential file (reset/replace file contents)\n"
    		"7. Read the list back from a sequential file\n" 
    		"(reset/replace current memory content)\n"
    		"0. Exit\n\n"
    		);
    		scanf("%d", &input);
    		switch(input)
    		{
    		case 1:
    		{
    			AddToEnd(ptrFirst,ptrLast);
    		}	
    		case 2:
    		{
    			AddToBeginning(ptrFirst,ptrLast);
    		}
    		case 3:
    		{
    			empty=isEmptyList(ptrFirst);
    			if(empty==1)
    			{
    				printf("The list is not empty\n\n");
    			}
    			else
    			{
    				printf("The list is empty\n\n");
    			}
    		}
    		case 4:
    		{
    			ResetList(ptrFirst,ptrLast);
    		}
    		case 5:
    		{
    			PrintList(ptrFirst);
    		}
    		case 6:
    		{
    		}
    		case 7:
    		{
    		}
    		default:
    		{
    			printf("Invalid entry, try again\n\n");
    		}
                    }
    	}
    }
    Last edited by JamesD; 03-13-2011 at 10:07 AM.

  4. #19
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    You're moving in the right direction...
    Now take the printout from case 3 and move it into the isemptylist function since that's the only place you use it. I always like to keep switch trees as nothing but a way to call functions. I seldom put code directly in a case statement. (You'll find out why the first time you have to debug one that goes wonkers on you...)

    Your while(input != 0) should also be moved to a case 0 : at the top of the chain. It only needs to contain, return 0; The while loop then becomes simply while (1) This makes little apparent difference but it does prevent having to traverse the entire switch chain before discovering you want it to exit.

    Also at the end of each case section you need to add a break statement... Absent that, case 1 will complete and fall directly into case 2... cascading down the entire chain.

  5. #20
    Registered User
    Join Date
    Mar 2011
    Location
    Windsor, Ontario
    Posts
    44
    added "break;" to all the cases, switched from void to int main and added the case 0. Thanks CommonTater. Can you see any other problems with it, as I have looked it over again and still can't find out why ResetList fails and it will only hold 1 set of values, when I scan in a second set it replaces and erases the first.

  6. #21
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by JamesD View Post
    added "break;" to all the cases, switched from void to int main and added the case 0. Thanks CommonTater. Can you see any other problems with it, as I have looked it over again and still can't find out why ResetList fails and it will only hold 1 set of values, when I scan in a second set it replaces and erases the first.
    When you add a new record to the beginning of the list, you need to take the current start pointer (which points to the current first item) set it into your new record as the pointer to the next item and then make the start pointer point to your new item.

    Similarly when adding to the end of the list you need to traverse the list, find the item with the null pointer (marking end of list) and set it's value to point to your new record. The pointer to the next item in your record then becomes NULL signalling the new end of list.

    Personally I think linked lists are icky things, I seldom use them if I can get out of it, but it's all about making absolutely certain that each record points to the next one in the chain.

  7. #22
    Registered User
    Join Date
    Mar 2011
    Location
    Windsor, Ontario
    Posts
    44
    I won't be able to work on it until later today but you helped a bunch. Thanks and I will try to fix up where they point to.

  8. #23
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by CommonTater View Post
    Similarly when adding to the end of the list you need to traverse the list, find the item with the null pointer (marking end of list) and set it's value to point to your new record. The pointer to the next item in your record then becomes NULL signalling the new end of list
    He's already keeping track of the last node. So all he has to do is make that node point to his new one, then set ptrLast to his new one.


    Quzah.
    Hope is the first step on the road to disappointment.

  9. #24
    Registered User
    Join Date
    Mar 2011
    Location
    Windsor, Ontario
    Posts
    44
    These are my codes for adding to the beginning:
    Code:
    case 2:
    {
    	AddToBeginning(ptrFirst,ptrLast);
    	break;
    }
    Code:
    void AddToBeginning(struct point *ptrF, struct point *ptrL)
    {		 
    	InputRecord(ptrNew);
    	ptrNew->ptrNext=NULL;
    	if(ptrF==NULL)
    		ptrF=ptrNew;
    	if(ptrF!=NULL)
    		ptrNew->ptrNext;
    	ptrL->ptrNext;
    }
    Code:
    void InputRecord(struct point *ptrNew)
    {
    	ptrNew=(struct point *)(malloc(sizeof(struct point)));
    	printf("Please enter the 2 Data points(x and y):\n");
    	ptrFirst=ptrNew;
    	if(ptrNew==NULL)
    		printf("No more memory.\n");
    	else
    	{
    		scanf("%d%d",&ptrNew->x, &ptrNew->y);	
    		printf("Please enter the label:\n");
    		scanf("%s", ptrNew->label);
    	}
    }
    In add to beginning I use ptrNew to get the input, and point it to ptrNext, the next pointer.
    Then I verify if ptrF is NULL if it is, it will point to ptrNew(the now first pointer). and if not point ptrNew to the next pointer and update ptrL to the last position. However this fails when I use it, can someone explain?

  10. #25
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    In InputRecord you should not set ptrFirst... Stay on task, create the new record and return a pointer to it.
    Code:
    struct point *InputRecord ( void )
    { struct point *ptrN= malloc(sizeof(struct point));
       if(ptrN == NULL) 
          { printf("No more memory.\n");
             exit(1);  }                           // this is a fatal error so exit if it happens
    
         // get new information 
         printf("Please enter the 2 Data points(x and y):\n");
         scanf("%d%d",&ptrN->x, &ptrN->y);	
         printf("Please enter the label:\n");
         scanf("%s", ptrN->label);
         return ptrN; }                         // return pointer to new struct
    In AddToBeginning again stay on task, here you only manipulate the pointers...
    Code:
    void AddToBeginning(struct point *ptrF)
    { struct point *temp = ptrf;                   // save pointer to first record
       ptrF = InputRecord();                     // get pointer to new first record
       ptrF->ptrNext = temp;  }                   // next in new record points to saved
    It's late here, I'm sure there's a minor error or two in there, but this should give you some idea.
    Last edited by CommonTater; 03-14-2011 at 10:25 PM. Reason: minor fix in add to beginning

  11. #26
    Registered User
    Join Date
    Mar 2011
    Location
    Windsor, Ontario
    Posts
    44
    How does the prototype look when using struct, I have:
    struct point InputRecord(void);
    however I think its trying to read it in as a declaration.

  12. #27
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by JamesD View Post
    How does the prototype look when using struct, I have:
    struct point InputRecord(void);
    however I think its trying to read it in as a declaration.
    struct point *InputRecord( void );

    It's always, the exact same as for the actual function, except with a semi-colon after.

  13. #28
    Registered User
    Join Date
    Mar 2011
    Location
    Windsor, Ontario
    Posts
    44
    Got addtobeginning and input record set now, and I think reset list is working, just gotta work on printlist
    Code:
    void PrintList(struct point *ptrF)
    {
    	struct point *pC = ptrF;
    	while(pC != NULL)
       {
    		printf("Label: %s\nx: %d y:%d\n\n", pC->label, pC->x, pC->y);
    		pC = pC->ptrNext;  // this is how a list is traversed
                    PrintList(struct point *pC)
       }	
    }
    How does this not work, it has a new pointer which points to the first and while it isn't null it prints out and then points to the next, anyone see what's wrong here?
    Last edited by JamesD; 03-14-2011 at 01:40 PM.

  14. #29
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Why are you recursively calling PrintList? Just call it once, and use a loop. If you are using recusion, you don't need the while loop. You just need an if check. Recursion is just another way to loop. Use one or the other here, not both.

    Quzah.
    Hope is the first step on the road to disappointment.

  15. #30
    Registered User
    Join Date
    Mar 2011
    Location
    Windsor, Ontario
    Posts
    44
    Assume it's the exact same but without recursion, when called nothing will print out, and that's got me confused.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. [BEGINNER] dynamic memory dumb question
    By arthurhess in forum C++ Programming
    Replies: 2
    Last Post: 12-14-2009, 02:53 PM
  2. Dynamic Linking & Memory usage
    By @nthony in forum C Programming
    Replies: 2
    Last Post: 06-02-2007, 09:57 PM
  3. Dynamic memory allocation...
    By dicorr in forum C Programming
    Replies: 1
    Last Post: 06-24-2006, 03:59 AM
  4. Is it necessary to write a specific memory manager ?
    By Morglum in forum Game Programming
    Replies: 18
    Last Post: 07-01-2002, 01:41 PM
  5. Dynamic Memory Allocation for fstream (binary)
    By kuphryn in forum C++ Programming
    Replies: 2
    Last Post: 12-12-2001, 10:52 AM