Thread: Read/Write linked lists from/to file

  1. #1
    Registered User
    Join Date
    Jan 2005
    Posts
    12

    Read/Write linked lists from/to file

    Hi, I'm trying to make a simple database, where I write a linked list to a file and then read it out again.

    I've been working on this for the last week and I've been stuck most of the time hehe But anywho, this is the code;

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
    #define TRUE 1
    
    void newname(void);
    void listfromfile(void);
    
    struct medlem
    {
    	char name[255];
    	char medlem[255];
    	struct medlem *ptrnext;
    };
    
    struct medlem *ptrfirst = NULL;
    
    void main(void)
    {
    char ch;
    
    while(TRUE)
    	{
    	printf("\nTryk 'e' for at indtast medlem\n");
    	printf("\nTryk 'p' for at laese fra fil\n");
    	printf("\nTryk 'q' for at quitte ;>\n");
    	ch = getche();
    	switch(ch)
    		{
    		case 'e':
    			newname(); break;
    		case 'p':
    			listfromfile(); break;
    		case 'q':
    			printf("\n");
    			exit(1);
    		default:
    			printf("\nForkert valg. \n");
    		}
    	}
    }
    
    
    void newname(void)
    {
    	FILE *fp;
    	struct medlem *ptrthis;
    	struct medlem *ptrfirst;
    
    	ptrthis = malloc(sizeof(struct medlem));
    	ptrfirst = malloc(sizeof(struct medlem));
    
    	if(ptrthis == NULL)
    	{
    		printf("Allocation failed.\n");
    		return;
    	}
    	ptrthis->ptrnext = ptrfirst;
    
    	if( (fp = fopen("c:\\database.txt", "a")) == NULL)
    		{
    		printf("\nCan't open file\n");
    		exit(1);
    		}
    	printf("\nEnter name: ");
    	gets(ptrthis->name);
    	printf("\nEnter number: ");
    	gets(ptrthis->medlem);
            //write to file
    	fwrite(ptrthis, sizeof(*ptrthis), 1, fp);
    	fclose(fp);
    
    }
    void listfromfile(void)
    {
    	struct medlem *ptrthis;
    	FILE *fp;
    	ptrthis = malloc(sizeof(struct medlem));
    	ptrfirst = ptrthis;
    	if( (fp = fopen("c:\\database.txt", "r")) == NULL)
    	{
    		printf("No such file\n");
    		exit(1);
    	}
    	if(ptrthis == NULL)
    	{
    		printf("NULL\n");
    		exit(1);
    	}
    	while(fread(ptrthis, sizeof(*ptrthis), 1, fp) ==1)
    	{
    		printf("\nNavn: %s\n", ptrthis->name);
    		printf("\nNumber: %s\n", ptrthis->medlem);
    		ptrthis = ptrthis->ptrnext;
    	}
    }
    Nothing happens really.. Something gets written to the file, but it aint' clear text :| And when I call the "listfromfile" function, nothing happens.

    Where did I fail?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > void main(void)
    int main
    See the FAQ and the Avatar!

    > while(fread(ptrthis, sizeof(*ptrthis), 1, fp) ==1)
    You need to malloc a node for each read, and link them together.
    You're presently calling malloc ONCE, and reading stuff into that.

    Actually, it's worse because you do this
    ptrthis = ptrthis->ptrnext;
    which goes off marching through someone elses memory.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Jan 2005
    Posts
    12
    Okay, int main it is then :P

    But how should I link them together?

    Something like this?

    Code:
    	while(fread(ptrthis, sizeof(*ptrthis), 1, fp) ==1)
    	{
    		printf("\nNavn: %s\n", ptrthis->name);
    		printf("\nNumber: %s\n", ptrthis->medlem);
                    ptrthis->ptrnext = malloc(sizeof(struct medlem));
    		ptrthis = ptrthis->ptrnext;
    	}
    Or?

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Pretty much - with these two things
    1. when the read fails, you end up with a spare node which contains no data (or more likely, junk data from the malloc). You'll need to get rid of this node.

    I normally read data into a normal variable, then only allocate space when I know the fread() was successful.

    2. Make sure that ptrthis->ptrnext = NULL;
    when you're done, to mark the end of the list.


    On other issues, you use gets().
    This too is bad, and it is also in the FAQ
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Jan 2005
    Posts
    12
    Hmm I can't find anything about gets() in the FAQ. Perhaps I'm not looking the right place :|

    Anywho, how do you do #1?

    something like;

    Code:
    while(fread(ptrthis, sizeof(*ptrthis), 1, fp) ==1)
    	{
            nametemp =  ptrthis->name;
            numbertemp = ptrthis->number;
            printf("%s", nametemp);
            printf("%d", numbertemp);
            }
    Or how do you mean? Sorry.. I'm not too good in C So any chance you could be a bit more specific?

  6. #6
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Consider reading the Linked List tutorial in the FAQ. As for gets, read this FAQ entry.

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

  7. #7
    Registered User
    Join Date
    Jan 2005
    Posts
    12
    Hi again

    I think I understand the basics of Linked Lists.. main problem for me, is how to write them to a file and read them out again.

    I've been to google, alltheweb and msn search. And I can't find anything that describes just that :/

  8. #8
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    What's not to understand?
    Code:
    void writeNode( FILE *fp, struct node *n )
    {
        if( fwrite( n, sizeof *n, 1, fp ) == 1 )
        {
            printf("Victory is mine!\n");
        }
        else
        {
            printf("Morons! I have morons on my payrole!\n");
        }
    }
    
    struct node *readNode( FILE *fp )
    {
        struct node *n = malloc( sizeof *n );
        if( n != NULL && fread( n, sizeof *n, 1, fp ) == 1 )
        {
            printf("Victory is mine!\n");
            n->next = NULL;
            n->prev = NULL;
        }
        else
        {
            printf("Morons! I have morons on my payrole!\n");
        }
        return n;
    }
    Quzah.
    Hope is the first step on the road to disappointment.

  9. #9
    Registered User
    Join Date
    Jan 2005
    Posts
    12
    What I don't understand is why fread returns 0..

    I've tried singlestepping my program and either I get an access violation, when I call the readfromfile() function or fread returns 0.

  10. #10
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Post your latest code.

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

  11. #11
    Registered User
    Join Date
    Jan 2005
    Posts
    12
    Here is my struct;

    Code:
    struct prs
    {
    	char name[255];
    	int number;
    	struct prs *ptrnext;
    };
    
    struct prs *ptrfirst = NULL;
    Here I enter a new member;

    Code:
    void newname()
    {
    	struct prs *ptrthis;						
    	char numstr[81];					
    	ptrthis = malloc(sizeof(struct prs));		
    	
    	if(ptrthis == NULL)
    	{
    		printf("Allocation failed\n");
    		return;
    	}
    
    	ptrthis->ptrnext = ptrfirst
    	ptrfirst = ptrthis;							
    
    	printf("\n\nEnter name: \n");
    	gets(ptrthis->name);
    	printf("\n\nEnter number: \n");
    	gets(numstr);
    	ptrthis->number = atoi(numstr);
    }
    Here I save my data to a file

    Code:
    void savetofile()
    {
    	FILE *fp;
    	struct prs *ptrthis;
    
    	if(ptrfirst == NULL)
    	{
    		printf("Empty.\n");
    		return;
    	}
    
    	ptrthis = ptrfirst;
    	if((fp=fopen("c:\\database.txt", "wb")) == NULL)
    	{
    		printf("No such file.\n");
    		return;
    	}
    	else
    	{
    		fwrite(&ptrthis, sizeof(*ptrthis), 1, fp);
    		fclose(fp);
    		printf("Saved to disk.\n");
    		system("PAUSE");
    	}
    }
    Here I read from the file and print. And it's here that fread returns 0 :|
    Code:
    void readfromfile()
    {
    	int nametemp;
    	int numbertemp = 0;
    	FILE *fp;
    	struct prs *ptrthis = malloc(sizeof(*ptrthis));
    	ptrthis = ptrfirst;
    
    	fp=fopen("c:\\database.txt", "ab");
    
    	while(fread(ptrthis, sizeof(*ptrthis), 1, fp) ==1)
    	{
    		printf("%s\n", ptrthis->name);
    		printf("%d\n", ptrthis->number);
    		ptrthis = ptrthis->ptrnext;
    	}
    
    	system("PAUSE");
    }
    Hopefully it's not to bad

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    A couple of days ago, I told you that your read from file needed to call malloc each time around the loop.

    Code:
    void readfromfile()
    {
        FILE *fp;
        struct prs temp;
        struct prs *next = NULL;
    
        fp=fopen("c:\\database.txt", "ab");
    
        while(fread(&temp, sizeof(temp), 1, fp) ==1)
        {
            struct prs *new = malloc( sizeof *new );
    
            // link new node into the list
            if ( ptrfirst == NULL ) {
                ptrfirst = new;
            } else {
                next->ptrnext = new;
            }
    
            // copy data
            new->number = temp.number;
            new->ptrnext = NULL;
    
            // this is now the tail of the list
            next = new;
        }
    
         fclose( fp );
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  13. #13
    Registered User
    Join Date
    Jan 2005
    Posts
    12
    Sorry Salem, but as I already said, I'm not that good at C

    And fread still returns 0.. so maybe it's my savetofile() function thats not working? Just wondering though, as I really have no idea

  14. #14
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Well your save is also broken as well

    > fwrite(&ptrthis, sizeof(*ptrthis), 1, fp);
    - You save only ONE thing - not the whole list
    - You save the address of the pointer itself, not what the pointer points at


    You need to traverse the list, and save each entry in the list
    Code:
    struct prs *this;
    for ( this = ptrfirst ; this != NULL ; this = this->ptrnext ) {
        fwrite(this, sizeof(*this), 1, fp);
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  15. #15
    Registered User
    Join Date
    Jan 2005
    Posts
    12
    That seemed to help. Now it's writing fine, afaik

    But fread still returns 0..

    Thank you for the help so far!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Basic text file encoder
    By Abda92 in forum C Programming
    Replies: 15
    Last Post: 05-22-2007, 01:19 PM
  2. C++ std routines
    By siavoshkc in forum C++ Programming
    Replies: 33
    Last Post: 07-28-2006, 12:13 AM
  3. Possible circular definition with singleton objects
    By techrolla in forum C++ Programming
    Replies: 3
    Last Post: 12-26-2004, 10:46 AM
  4. help with linked lists and file i/o
    By Mazer in forum C++ Programming
    Replies: 1
    Last Post: 10-21-2003, 01:59 PM