Thread: Input/output question

  1. #1
    Registered User
    Join Date
    Mar 2005
    Posts
    15

    Input/output question

    Basically I must create a library system which prompt user for some books input, then we save the books to file and when we open the program for the second time we can load the books that we have saved before int the linked lists.

    Well, my problem is I have no idea how to read from the file and load the books back to the linked list when we run the program for the second time. So that we can access the book from the linked list.
    Any suggestion?


    Here is my code:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct book
    {
    	char title[21];	/* 20 + null-terminator */
    	char author[21];	/* 20 + null-terminator */
    	char status[21];
    	struct book* next;
    }BOOK;
    
    void display_lists( const BOOK* ptr);
    void save_book(BOOK* ptr);
    BOOK* load_data(BOOK* book)
    BOOK* add_books(void);
    /*BOOK* find_nth_book( BOOK* ptr, int n);
    BOOK* add_book_at_nth( BOOK* ptr, BOOK* new, int n);
    BOOK* delete_nth_book( BOOK* ptr, int n, int* success_flag);*/
    
    int main()
    {
    	BOOK *start;
    	start = add_books();
    	save_book(start);	/* save book list to file */
    	display_lists(start);
    	return 0;
    }
    
    /*	add_book allocates run-time storage for nodes. It builds 
    	the linked list and stores user-supplied title and author in 
    	the members of the nodes. It returns a pointer to the first 
    	such node */
    
    BOOK* add_books(void)
    {
    	BOOK *current, *first;
    	
    	char ans[2];
    	
    	/* allocate first node */
    	current = first = malloc( sizeof(BOOK) );
    	/* store title of first book */
    	printf( "\nPlease enter book's title: \n" );
    	gets(current -> title);
    	printf( "\nPlease enter book's author: \n" );
    	gets(current -> author);
    	strcpy( current -> status, "available");
    	/* prompt user about another book */
    	printf( "\n\nAdd another? (y/n)\t" );
    	gets(ans);	
    
    	/* Add book to list until user signals halt. */
    	while ( *ans != 'n' && *ans != 'N')
    	{
    		/* try to allocate another book node */
    		if ( ( current -> next =
    			   malloc( sizeof ( BOOK ) ) ) == NULL )
    		{
    			printf( "Out of memory\nCan't add more books\n" );
    			return first;
    		}
    		current = current -> next;
    
    		/* store name of next book */
    		printf( "\nPlease enter book's title: \n" );
    		gets(current -> title);
    		printf( "\nPlease enter book's author: \n" );
    		gets(current -> author);
    		strcpy( current -> status, "available");
    
    		/* prompt user about another book */
    		printf( "\nAdd another(y/n)? " );
    		gets(ans);	
    	}
    	/* set link in last node to NULL */
    	current -> next = NULL;
    	return first;
    }
    
    /*	display_lists steps through the linked list pointed to by 
    	ptr and prints the member name in each node as well as the
    	position of the node in the list */
    
    void display_lists( const BOOK* ptr)
    {
    	printf( "\n\n" );
    	printf( "%-15s\t%-15s\t%-15s\n", "Book Title", "Author", "Status");
    	while( ptr != NULL )
    	{
    		printf( "%-15s\t%-15s\t%-15s\n",  ptr->title, ptr->author, ptr->status);
    		ptr = ptr->next;
    	}
    }
    
    /*	Save book list to book_list.dat	*/
    
    void save_book(BOOK* ptr)
    {
    	FILE *fptr;
    	fptr = fopen ("book_list.txt", "a");
    
    	while (ptr!=NULL)
    	{
    		fputs(ptr->title, fptr);
    		fputs("\t\t", fptr);
    		fputs(ptr->author, fptr);
    		fputs("\t\t", fptr);
    		fputs(ptr->status, fptr);
    		fputc('\n', fptr);
    
    		ptr = ptr->next;
    	}
    	fclose(fptr);
    }
    
    /* Open book_list.txt and read the file and store it in the linked list	*/
    BOOK* load_data(BOOK* book)
    {
    	FILE *fptr;
    	fptr = fopen ("book_list.txt", "rb");
    	
    	/* Function implementation */
    }

  2. #2
    Senior Member joshdick's Avatar
    Join Date
    Nov 2002
    Location
    Phildelphia, PA
    Posts
    1,146
    fscanf() works just like scanf(), and you could also use fgets().
    FAQ

    "The computer programmer is a creator of universes for which he alone is responsible. Universes of virtually unlimited complexity can be created in the form of computer programs." -- Joseph Weizenbaum.

    "If you cannot grok the overall structure of a program while taking a shower, you are not ready to code it." -- Richard Pattis.

  3. #3
    Registered User
    Join Date
    Mar 2005
    Posts
    15
    I've tried using fscanf but the result is it only read a string at a time, if there is white space it will skip and move to the next string. If we use fgets it will read the whole string in the text and save it to the pointer.

    What I need is to read the file per title, author, status. Then save each of them back to the element of structure.

    Using string tokenizer maybe?

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct book
    {
    	char title[21];		/* 20 + null-terminator */
    	char author[21];	/* 20 + null-terminator */
    	char status[21];
    	struct book* next;
    }BOOK;
    
    int main()
    {
    	BOOK b[2];
    	FILE *fptr;
    	
    	fptr = fopen ("book_list.txt", "r");
    	
    	fscanf(fptr, "%s\t\t%s\t\t%s", b[0].title, b[0].author, b[0].status);
    	fscanf(fptr, "%s\t\t%s\t\t%s", b[1].title, b[1].author, b[1].status);
    
    	printf("%s\t\t%s\t\t%s\n", b[0].title, b[0].author, b[0].status);
    	printf("%s\t\t%s\t\t%s\n", b[1].title, b[1].author, b[1].status);
    
    	return 0;
    }
    In book_list.txt:
    Code:
    Robinson Crusoe		Daniel Defoe		available
    Rovet & Vorce		J. Aramith		                available
    output:
    Code:
    Robinson                              Crusoe                                Daniel
    Defoe                       available                                          Rovet
    Last edited by vice; 04-26-2005 at 08:04 AM.

  4. #4
    Senior Member joshdick's Avatar
    Join Date
    Nov 2002
    Location
    Phildelphia, PA
    Posts
    1,146
    Try getting rid of the '\t' characters in the fscanf() arguments. I'm pretty sure that when that function reads in strings, it skips whitespace like tabs.
    FAQ

    "The computer programmer is a creator of universes for which he alone is responsible. Universes of virtually unlimited complexity can be created in the form of computer programs." -- Joseph Weizenbaum.

    "If you cannot grok the overall structure of a program while taking a shower, you are not ready to code it." -- Richard Pattis.

  5. #5
    Registered User
    Join Date
    Mar 2005
    Posts
    15
    What about if i want to read the whitespace in the string like in "Robinson Crusoe", can we use fscanf("%s", .....)

  6. #6
    Senior Member joshdick's Avatar
    Join Date
    Nov 2002
    Location
    Phildelphia, PA
    Posts
    1,146
    In that case what I suggest is that you read in the whole line using fgets(). Then break it up into tokens using strtok() where '\t' is your delimiter.
    FAQ

    "The computer programmer is a creator of universes for which he alone is responsible. Universes of virtually unlimited complexity can be created in the form of computer programs." -- Joseph Weizenbaum.

    "If you cannot grok the overall structure of a program while taking a shower, you are not ready to code it." -- Richard Pattis.

  7. #7
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    You could also use the %[ specifier for fscanf to read up to a tab.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct book
    {
       char title[21];      /* 20 + null-terminator */
       char author[21];  /* 20 + null-terminator */
       char status[21];
       struct book* next;
    }BOOK;
    
    int main()
    {
       FILE *fptr = fopen ("book_list.txt", "r");
       if ( fptr )
       {
          BOOK b[10];
          size_t i = 0;
          while ( fscanf(fptr, "%20[^\t]\t%20[^\t]\t%20[^\n]%*c",
                         b[i].title, b[i].author, b[i].status) == 3 )
          {
             printf("%s\t\t%s\t\t%s\n", b[i].title, b[i].author, b[i].status);
             ++i;
          }
          fclose(fptr);
       }
       return 0;
    }
    
    /* my output
    Robinson Crusoe		Daniel Defoe		available
    Rovet & Vorce		J. Aramith		available
    */
    Something similar could be done with fgets/sscanf as well.
    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.*

  8. #8
    Registered User
    Join Date
    Mar 2005
    Posts
    15
    Yeah it works thanks a lot
    What "%*c" in your code used for?

  9. #9
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by vice
    Yeah it works thanks a lot
    What "%*c" in your code used for?
    Code:
          while ( fscanf(fptr, "%20[^\t]\t%20[^\t]\t%20[^\n]%*c",
                         b[i].title, b[i].author, b[i].status) == 3 )
    This means to read a string of up to 20 characters into status, stopping at a newline. Then consume -- read and discard -- the next character (the newline).
    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.*

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Debugging question
    By o_0 in forum C Programming
    Replies: 9
    Last Post: 10-10-2004, 05:51 PM
  2. Question about pointers #2
    By maxhavoc in forum C++ Programming
    Replies: 28
    Last Post: 06-21-2004, 12:52 PM
  3. Question...
    By TechWins in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 07-28-2003, 09:47 PM
  4. Question about linked lists.
    By cheeisme123 in forum C++ Programming
    Replies: 6
    Last Post: 02-25-2003, 01:36 PM
  5. Question, question!
    By oskilian in forum A Brief History of Cprogramming.com
    Replies: 5
    Last Post: 12-24-2001, 01:47 AM