Thread: Dynamic Memory and Files

  1. #1
    Registered User
    Join Date
    Mar 2011
    Location
    Windsor, Ontario
    Posts
    44

    Dynamic Memory and Files

    I am making a program using dynamic memory and was able to successfully code it going into the file, but need help reading it back, I am stuck in the function Load.
    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    
    struct point
    {
    	int x; //point x
    	int y; //point y
    	char label[21]; //label of 2 points
    	struct point *ptrNext;	// self referential pointer
    };
    //Global:
    struct point *ptrFirst = NULL;//empty list (ptrFirst is the head of the list
    struct point *ptrLast = NULL;//empty list (ptrLast is the tail of the list)
    //Prototypes:
    struct point *CreatePoint();
    int isEmptyList(struct point *ptrF);
    void PrintList(struct point *ptr);
    void ResetList();
    struct point *AddToBeginning(struct point *ptrNew);
    struct point *AddToEnd(struct point *ptrNew);
    struct point* InputRecord(struct point *ptrNew); // used by Add to interactively get the values from the user
    void Save(const char* filename);
    void Load(const char* filename);
    
    int count=0;
    
    int main()
    {
    	int run=1;
    	int	input=1;
            int result=0;
    	while(run==1)
    	{
    		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 0:
    			{
    				ResetList(ptrFirst);
    				run = 0;
    				break;
    			}
    			case 1:
    			{
    				AddToEnd(InputRecord(CreatePoint()));
    				break;
    			}	
    			case 2:
    			{
    				AddToBeginning(InputRecord(CreatePoint()));
    				break;
    			}
    			case 3:
    			{
    				if(isEmptyList(ptrFirst)==0)
    					printf("The list is empty\n\n");
    				else
    					printf("The list is not empty\n\n");
    				break;
    			}
    			case 4:
    			{
    				ResetList(ptrFirst);
    				break;
    			}
    			case 5:
    			{
    				PrintList(ptrFirst);
    				break;
    			}
    			case 6:
    			{
    				result=Save("data.dat");
    				break;
    			}
    			case 7:
    			{
    				result=Load("data.dat");
    				break;
    			}
    			default:
    			{
    				printf("Invalid entry, try again\n\n");
    				break;
    			}
    		}
    	}
    }	
    
    
    //CreatePoint creates using dynamic memory allocation a new record of type point
    //Input: assumes enough dynamic memory is available
    //Output: returns a pointer to the enw point, or NULL if not enough memory
    struct point *CreatePoint()
    {
    	return (struct point *)(malloc(sizeof(struct point)));
    }
    
    //isEmptyList checks if the list is empty
    int isEmptyList(struct point *ptrF)
    {
    	if(ptrF==NULL)
    		return 0;
    	else
    		return 1;
    }
    
    //PrintList will print out the contents of the list
    void PrintList(struct point *ptr)
    {
    	if(ptr!=NULL)
    	{
    		printf("x: %d\ny: %d\nlabel: %s\n\n",ptr->x,ptr->y,ptr->label);
    		PrintList(ptr->ptrNext);
    	}
    }
    
    //ResetList will empty or free() the contents of the list
    void ResetList()
    {
    	struct point *ptrDel=ptrFirst;
    	
    	while(ptrFirst!=NULL)
    	{
    		ptrDel=ptrFirst;
    		ptrFirst=ptrFirst->ptrNext;
    		free(ptrDel);
    	}
    }
    
    //AddToBeginning adds a new record to the beginning of the list
    //Input: assumes a valid record is given and initialized properly
    //Output: adds the record to the beginning, returns a pointer to that record
    struct point* AddToBeginning(struct point *ptrNew)
    {
    	//case 1: ptrNew is not valid(ie. NULL - nothing to add!)
    	if(ptrNew==NULL)
    		return NULL;
    	//case 2: add the record to an empty list
    	if(ptrFirst==NULL)
    	{
    		ptrFirst=ptrNew;
    		ptrLast=ptrNew;
    	}
    	//case 3: you are adding new record to an existing list	
    	else
    	{
    		ptrNew->ptrNext=ptrFirst;
    		ptrFirst=ptrNew;	
    	}	
    		
    	return ptrNew;	
    }
    
    //AddToEnd will add a point to the end of the list
    struct point *AddToEnd(struct point *ptrNew)
    {
    	//case 1: ptrNew is not valid(ie. NULL - nothing to add!)
    	if(ptrNew==NULL)
    		return NULL;
    	//case 2: add the record to an empty list
    	if(ptrFirst==NULL)
    	{
    		ptrFirst=ptrNew;
    		ptrLast=ptrNew;
    	}
    	//case 3: add the record to an existing list
    	else
    	{
    		ptrLast->ptrNext = ptrNew;
    		ptrLast = ptrNew;		
    	}
    }
    
    //InputRecord sets the initial values of a new record
    //Input: a pointer to an existing record
    //Output: sets the int value to a value from the keyboard, and null to all pointers
    //        and returns the same pointer to that initialized record
    struct point* InputRecord(struct point *ptrNew)
    {
    	if(ptrNew==NULL) //fail-safe: check for valid pointer
    		return NULL;
    	
    	printf("Please enter the data for x and y:\n");
    	scanf("%d%d", &ptrNew->x,&ptrNew->y);
    	printf("Please enter the label for the data:\n");
    	scanf("%s", ptrNew->label);
    	
    	ptrNew->ptrNext=NULL;
    	return ptrNew;
    }
    
    int Save(const char* filename)
    {
    	count=0;
    	FILE* outfile;
    	struct point *ptrCurrent = ptrFirst;
    	if(isEmptyList(ptrFirst)==0)
    		return 0;
    	
    	outfile = fopen(filename, "w");
    
    	if (outfile == NULL)
    		return 0;
    
    	while(ptrCurrent != NULL)
    	{
    		count++;
    		fprintf(outfile, "%d %d %s",ptrCurrent->x,ptrCurrent->y,ptrCurrent->label);
    		if(ptrCurrent->ptrNext != NULL)
    			fprintf(outfile, "\n");
    		ptrCurrent=ptrCurrent->ptrNext;
    	}
    
    	fclose(outfile);
    }
    
    int Load(const char* filename)
    {
    	FILE* infile;
    	struct point *ptrNew = NULL;
    	
    	infile = fopen(filename, "r");
    	
    	if (infile == NULL)
    		return 0;
    	
    	// ready to read from file, reset (clear) current list!
    	ResetList(ptrFirst);
    	
    	while(!feof(infile))
    	{
    		ptrNew = (struct point *) (malloc(sizeof(struct point)));
    		if (ptrNew == NULL) 
    			break;
    
    
            //STUCK HERE
    
    		
    		
    }
    Just wondering how you would read it back in using no arrays, any ideas? For now I will assume the words input have no spaces for convenience.
    Last edited by JamesD; 03-24-2011 at 12:13 AM.

  2. #2
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Lots of idea's, but which one is a good one, depends on the data. Post up a sample of the data, and what the problem is loading it.

    The more detailed you are, the more specific any help can be.

  3. #3
    Registered User
    Join Date
    Mar 2011
    Location
    Windsor, Ontario
    Posts
    44
    Its just basic stuff, ex input:
    1
    2
    point1
    8
    9
    point2
    12
    34
    point3

    Just digits for x and y and a string to label the points. Again assume there is no spaces in the string. I am confused as how to read that back from a file, it stores to the file in such a way:
    1 2 point1
    8 9 point2
    12 34 point3

    I have to try and read this back without using arrays.

  4. #4
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by JamesD View Post
    Its just basic stuff, ex input:
    1
    2
    point1
    8
    9
    point2
    12
    34
    point3

    Just digits for x and y and a string to label the points. Again assume there is no spaces in the string. I am confused as how to read that back from a file, it stores to the file in such a way:
    1 2 point1
    8 9 point2
    12 34 point3

    I have to try and read this back without using arrays.
    Given....
    Code:
    struct point
    {
    	int x; //point x
    	int y; //point y
    	char label[21]; //label of 2 points
    	struct point *ptrNext;	// self referential pointer
    };
    I would use formatted scanning techniques...
    Code:
    scanf("%d %d %20s",&point.x,&point.y,point.label);
    Substituting the actual name of the point struct, of course.

    Of course there is a much better way to do this... simply write the struct itself to the file and read it back in a single operation.

  5. #5
    Registered User
    Join Date
    Mar 2011
    Location
    Windsor, Ontario
    Posts
    44
    I looked up putting a whole struct to a file, and tried it out in my program and got this:
    Code:
    int Save(const char* filename)
    {
    	FILE* outfile;
    	int count = 0;	// how many records saved
    	struct point *ptrCurrent = ptrFirst;
    
    
    	// if the list is empty, leave!
    	if (isEmptyList())
    		return 0;
    
    	outfile = fopen(filename, "w");
    
    	if (outfile == NULL)
    		return 0;
    
    	while(ptrCurrent != NULL)
    	{		
    		count++;
    		fwrite(ptrCurrent, sizeof(struct point), 1, outfile);
    		ptrCurrent=ptrCurrent->ptrNext;
    	}
    
    	fclose(outfile);
    	return count;
    }
    
    int Load(const char* filename)
    {
    	FILE* infile;
    	int count = 0;	// how many records saved
    	struct point *ptrNew = NULL;
    
    	infile = fopen(filename, "r");
    
    	if (infile == NULL)
    		return 0;
    
    	// ready to read from file, reset (clear) current list!
    	ResetList();
    
    	while(!feof(infile))
    	{		
    		ptrNew = (struct point *) (malloc(sizeof(struct point)));
    		if (ptrNew == NULL) break;
    
    		fread(ptrNew, sizeof(struct point), 1, infile);
    		ptrNew->ptrNext = NULL;
    	}
    
    	fclose(infile);
    	return count;		
    }
    Good news is I think it saves properly, just won't read back in, any ideas?

  6. #6
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    Code:
    int Load(const char* filename)
    {
    	FILE* infile;
    	int count = 0;	// how many records saved
    	struct point *ptrNew = NULL;
    
    	infile = fopen(filename, "r");
    
    	if (infile == NULL)
    		return 0;
    
    	// ready to read from file, reset (clear) current list!
    	ResetList();
    
    	while(!feof(infile))
    	{		
    		ptrNew = (struct point *) (malloc(sizeof(struct point)));
    		if (ptrNew == NULL) break;
    
    		fread(ptrNew, sizeof(struct point), 1, infile);
    		ptrNew->ptrNext = NULL;
    	}
    
    	fclose(infile);
    	return count;		
    }
    ptrNew is a local variable within the function; it ceases to exist once you leave the function, resulting in a memory leak and losing all your data. You also repeatedly overwrite this variable, again creating a memory leak.

  7. #7
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    To make that work you will have to pass in a pointer to the root of your linked list. Set that with your first record then modify each record as you add the new one... that is...

    1) load first record at PtrFirst which is passed into the function.
    2) load the next record and modify the PtrNext in the previous record to point to it.
    3) loop to step 2

    So... when loading record #7 (for example) you have to modify #6 to point to it.... right up the chain.

    Then, when you return from the function, PtrFirst which was handed in, is successfully pointing to the entire loaded list.
    Last edited by CommonTater; 03-24-2011 at 10:58 AM.

  8. #8
    Registered User
    Join Date
    Mar 2011
    Location
    Windsor, Ontario
    Posts
    44
    This accounts for ptrFirst and doesn't re-write ptrNew over and over, however it fails to bring up any results either.. And I'm not sure why
    Code:
    int Load(const char* filename)
    {
    	FILE* infile;
    	int count = 0;	// how many records saved
    	struct point *ptrNew = NULL;
    
    	infile = fopen(filename, "r");
    
    	if (infile == NULL)
    		return 0;
    
    	// ready to read from file, reset (clear) current list!
    	ResetList();
    	
    	while(!feof(infile))
    	{		
    		ptrNew = (struct point *) (malloc(sizeof(struct point)));
    		if (ptrNew == NULL) 
    			break;
    
    		if(ptrFirst==NULL)
    		{
    			fread(ptrNew, sizeof(struct point), 1, infile);
    			ptrFirst=ptrNew;
    			ptrLast=ptrNew;
    		}
    		else
    		{
    			fread(ptrNew, sizeof(struct point), 1, infile);
    			ptrNew->ptrNext=ptrFirst;
    			ptrFirst=ptrNew;
    		}
    		ptrNew->ptrNext=NULL;	
    	}
    
    	fclose(infile);
    	return count;		
    }

  9. #9
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    You are trying to update the current record to point to the next... which you cannot know yet since you haven't done malloc() for it. You need to update the *previous* record to point to the one you just loaded.

  10. #10
    Registered User
    Join Date
    Mar 2011
    Location
    Windsor, Ontario
    Posts
    44
    Got it working, thanks for the help.

  11. #11
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    No worries... Linked lists are totally weird to do the first time.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. New to classes with dynamic memory, looking for some help
    By Freddy92 in forum C++ Programming
    Replies: 4
    Last Post: 03-08-2011, 02:45 AM
  2. To find the memory leaks without using any tools
    By asadullah in forum C Programming
    Replies: 2
    Last Post: 05-12-2008, 07:54 AM
  3. reading files into memory
    By bobthebullet990 in forum C Programming
    Replies: 3
    Last Post: 11-30-2005, 03:39 PM
  4. pointers
    By InvariantLoop in forum C Programming
    Replies: 13
    Last Post: 02-04-2005, 09:32 AM
  5. Manipulating the Windows Clipboard
    By Johno in forum Windows Programming
    Replies: 2
    Last Post: 10-01-2002, 09:37 AM