Thread: Read/Write linked lists from/to file

  1. #16
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Post your latest then
    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.

  2. #17
    Registered User
    Join Date
    Jan 2005
    Posts
    12
    Okay

    Savetofile();

    Code:
    void savetofile()
    {
    	FILE *fp;
    	struct prs *this;
    	struct prs *ptrthis;
    
    	if(ptrfirst == NULL)
    	{
    		printf("Empty.\n");
    		return;
    	}
    
    	ptrthis = ptrfirst;
    	if((fp=fopen("c:\\database.txt", "ab")) == NULL)
    	{
    		printf("No such file.\n");
    		return;
    	}
    	else
    	{
    	for ( this = ptrfirst ; this != NULL ; this = this->ptrnext ) 
    	{
        fwrite(this, sizeof(*this), 1, fp);
    	fclose(fp);
    	}
    	printf("Saved.\n");
    	}
    }
    And this is my readfromfile();

    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) > 0)
        {
            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 );
    }

  3. #18
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Try not closing the file AFTER writing the first record, but AFTER writing all the records.
    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.

  4. #19
    Registered User
    Join Date
    Jan 2005
    Posts
    12
    Ahh yes. Hmm, didn't help though :/

    fread still returns 0.. I'm not sure where the error is.

    Any other suggestions? This program have annoyed me for the past week

  5. #20
    Registered User
    Join Date
    Jan 2005
    Posts
    12
    No one? :|

  6. #21
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    1) Write a program that will write the data in the form of text to your file. (Just fprintf each section.
    2) Make sure there's actually data in the file.
    3) Convert that into a program that just uses fwrite to write the structure.
    4) Make sure there's data in the file.
    5) Try using fread to read just one structure.

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

  7. #22
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Try this!
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct {
        char  name[10];
        int   age;
    } data_st;
    
    typedef struct node_tag {
      data_st   data;
      struct node_tag  *next;
    } node_st;
    
    node_st *ListAlloc ( void ) {
      node_st *new = malloc( sizeof *new );
      if ( new ) {
        new->next = NULL;
      }
      return new;
    }
    
    node_st *ListFill ( data_st *data ) {
      node_st *new = ListAlloc( );
      if ( new ) {
        new->data = *data;
      }
      return new;
    }
    
    node_st *ListAppend ( node_st *head, data_st *data ) {
      node_st *new = ListFill( data );
      if ( new ) {
        if ( !head ) {
          head = new;
        } else {
          node_st *tail = head;
          while ( tail->next ) tail = tail->next;
          tail->next = new;
        }
      }
      return head;
    }
    
    void ListSave ( node_st *list, char *filename ) {
      FILE *fp = fopen( filename, "wb" );
      while ( list ) {
        fwrite( &list->data, sizeof list->data, 1, fp );
        list = list->next;
      }
      fclose(fp);
    }
    
    node_st *ListLoad ( char *filename ) {
      FILE *fp = fopen( filename, "rb" );
      node_st *list = NULL;
      data_st data;
      while ( fread( &data, sizeof data, 1, fp ) ) {
        list = ListAppend( list, &data );
      }
      fclose(fp);
      return list;
    }
    
    void ListPrint ( node_st *list ) {
      while ( list ) {
        printf( "%s %d\n", list->data.name, list->data.age );
        list = list->next;
      }
    }
    
    int main ( ) {
      data_st test[] = {
        { "fred",   22 },
        { "barney", 23 },
        { "wilma",  24 },
        { "betty",  25 },
      };
      node_st *list = NULL, *loaded = NULL;
      int i;
    
      /* create a list */
      for ( i = 0 ; i < 4 ; i++ ) {
        list = ListAppend( list, &test[i] );
      }
      ListPrint( list );
    
      /* save and load it */
      ListSave( list, "wibble.bin" );
      loaded = ListLoad( "wibble.bin" );
      ListPrint( loaded );
    
      return 0;
    }
    This is what the binary file looks like
    Code:
    > od -t x1z wibble.bin
    0000000 66 72 65 64 00 00 00 00 00 00 cc cc 16 00 00 00  >fred............<
    0000020 62 61 72 6e 65 79 00 00 00 00 cc cc 17 00 00 00  >barney..........<
    0000040 77 69 6c 6d 61 00 00 00 00 00 cc cc 18 00 00 00  >wilma...........<
    0000060 62 65 74 74 79 00 00 00 00 00 cc cc 19 00 00 00  >betty...........<
    0000100
    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.

  8. #23
    Registered User
    Join Date
    Jun 2004
    Posts
    277
    Salem why do you use pointers to functions? I mean I saw many implementations of Linked Lists and people usually don't use it. I've read your code its damm clear so I liked a lot your implementation. I just can't figure out why using it K&R gave me nothing great as feed back, any suggestions? I will google a while but if you could give me some tips I would be very gratefull thanks.

  9. #24
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    What? There's no function pointers there. There are functions that return pointers. But there are no function pointers.

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

  10. #25
    Registered User
    Join Date
    Jun 2004
    Posts
    277
    Quote Originally Posted by quzah
    What? There's no function pointers there. There are functions that return pointers. But there are no function pointers.

    Quzah.
    Oh I got it thanks a lot!

  11. #26
    UT2004 Addict Kleid-0's Avatar
    Join Date
    Dec 2004
    Posts
    656
    And to top this thread off with a cherry on top:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    // A very strange linked list
    struct mendel
    {
       char name[255];
       char SS[255];
       struct mendel *next;
    };
    
    // Mendel linked list data holder
    struct
    {
       struct mendel *first;
       struct mendel *curr;
       struct mendel *decoy;   // Used just in case malloc fails
    } ListStatus;
    
    
    
    // Add to the linked list
    void add( void );
    
    // List all of the information from the linked list
    void listAll( void );
    
    
    
    int main( void )
    {
       // c = temperary character for input
       // n = temperary character extracts bad \n
       
       char c;
       int n;
    
       // Make sure the linked list is NULL for now
    
       ListStatus.first = NULL;
       ListStatus.curr = NULL;
    
       // Ask the user for his/her next action
       
       puts( "'a' add data\n"
             "'l' list all\n"
             "'q' quit" );
       printf( "~> " );
    
       // Input from the user their linked list request
             
       while( c = getchar( ) )
       {
          while( ( n=getchar( ) ) != EOF && n != '\n' );
          switch( c )
          {
             case 'a':
                add( ); break;
             case 'l':
                listAll( ); break;
             case 'q':
                puts( "Good bye." ); return 0;
             default:
                puts( "Bad input :( " );
          }
          printf( "~> " );
       }
    
       // Return success
    
       return 0;
    }
    
    
    
    
    // Add to the linked list
    void add( void )
    {
       // fdb = File database for the linked list
       // ptr = Helps remove '\n' from fgets()
       
       FILE *fdb;
       char *ptr;
    
       // Construct working linked list, if not already made
    
       if( ListStatus.first == NULL )
       {
          // This is our first time adding, so let's setup the first pointer
          // Just in case allocation screws up, we have a decoy
          
          ListStatus.decoy = malloc( 1 * sizeof( *ListStatus.decoy ) );
          if( !ListStatus.decoy )
          {
             puts( "Allocation failure" ); return;
          }
          ListStatus.first = ListStatus.decoy;
          ListStatus.curr = ListStatus.first;
       }
       else
       {
          // This is our ++1 time running, prepare to add to the previous current branch
          
          ListStatus.decoy = malloc( 1 * sizeof( *( ListStatus.decoy ) ) );
          if( !ListStatus.decoy )
          {
             puts( "Allocation failure" ); return;
          }
          ListStatus.curr->next = ListStatus.decoy;
          ListStatus.curr = ListStatus.curr->next;
       }
    
       // Prepare the database for input
       
       if( ( fdb = fopen( "database.txt", "a+" ) ) == NULL )
       {
          puts( "Can't open database for editing" );
          return;
       }
    
       // Enter a name; remove newlines when necessary
       
       printf( "Enter name: " );
       if( fgets( ListStatus.curr->name, sizeof( ListStatus.curr->name ), stdin ) != NULL )
          if( ( ptr=strchr( ListStatus.curr->name, '\n' ) ) != NULL ) *ptr='\0';
    
       printf( "Enter SS: " );
       if( fgets( ListStatus.curr->SS, sizeof( ListStatus.curr->SS ), stdin ) != NULL )
          if( ( ptr=strchr( ListStatus.curr->SS, '\n' ) ) != NULL ) *ptr='\0';
    
       // Write the name/SS to the database
       
       fwrite( ( void* )( ListStatus.curr ), sizeof( *( ListStatus.curr ) ), 1, fdb);
    
       // Close the file pointer to the database
       
       fclose( fdb );
    }
    
    
    
    // List all of the data in the linked list
    void listAll( void )
    {
       // Make sure the linked list is not empty
       
       if( ListStatus.first == NULL )
       {
          puts( "No data to list" );
          return;
       }
    
       // ptr = Cycles through all of the linked list
       // c = Keeps track of what part of the list we're on
       
       struct mendel *ptr = ListStatus.first;
       int c=1;
    
       // Output the whole linked list
       
       do
       {
          printf(  "# %d:\n"
                   "%s\n"
                   "%s\n"
                   "------\n", c++, ptr->name, ptr->SS );
       } while( ( ptr=ptr->next ) != NULL );
    }

  12. #27
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Don't make me point you to the FAQ:
    Code:
       char c;
       /* ... */
       while( c = getchar( ) )
    If you are using string functions such as strchr, you should #include <string.h>.

    If you are using C99, it would be worth mentioning. C90 is still the reigning implementation:
    Code:
    void listAll( void )
    {
       // Make sure the linked list is not empty
       
       if( ListStatus.first == NULL )
       {
          puts( "No data to list" );
          return;
       }
    
       // ptr = Cycles through all of the linked list
       // c = Keeps track of what part of the list we're on
       
       struct mendel *ptr = ListStatus.first;
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  13. #28
    UT2004 Addict Kleid-0's Avatar
    Join Date
    Dec 2004
    Posts
    656
    Next time Dave, next time you won't find any errors, and I'll be scott free! lol

    Gah!
    Code:
    int getchar( void );
    Code:
    void listAll( void )
    {
       // Make sure the linked list is not empty
       
       if( ListStatus.first == NULL )
       {
          puts( "No data to list" );
          return;
       }
    
       // ptr = Cycles through all of the linked list
       // c = Keeps track of what part of the list we're on
       
       struct mendel *ptr = ListStatus.first; // <-- What's wrong with this?

  14. #29
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Code:
    struct mendel *ptr = ListStatus.first; // <-- What's wrong with this?
    It is either C99 or C++ to declare a variable after a statement. If it's C++, it's off-topic here; if it's C99, it is worth mentioning.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  15. #30
    UT2004 Addict Kleid-0's Avatar
    Join Date
    Dec 2004
    Posts
    656
    Thank you Dave, I'll write that on my board...God bless C!
    <gesture deleted by Salem>

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