Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations biv343 on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Problem reading struct in a file 1

Status
Not open for further replies.

Exode

Programmer
Feb 17, 2004
14
CA
Hi all. I'm currently working on a small project which consists of reading struct from a file. The file contains info on separated lines and each bunch of 6 lines form a struct. I have some little problems and if anyone could help me I would really appreciate !

Currently I have 2 problems when compiling:
-"BOOK book;"
-"books[num_books] = book;"

I thought we could declare a new instance of a struct in the function but it gives me the "Undeclared identifier"...

The other error says "cannot convert from int to bookInfo", but I'm trying to assign a value from a struct book to the num_books value of the struct array, which is a struct...

Any help would be appreciate. Thanks

Code:
#include "stdafx.h"
#include "stdio.h"
#include <stdlib.h>

/* Struct containing the informations on a book */
struct book
{
    char title[80];
    char autor[40];
    char editor[20];
    char ISBN[10];
    char subject[20];
    int releaseDate;
};
typedef struct book bookInfo;


int main()
{
  char c[50];              // Store line we read
  FILE *file;             // File containing the data
  bookInfo *books;        // Array of books, UNKNOWN size !
  char *buff;             // Buffer to read in the file
  int num_books = 0;     // Keep the count of number read in
  int i, j;

  /* First step we open the file and see if it's correct */
  file = fopen("books.txt", "r");
  if(file==NULL) 
     {
     printf("Error: can't open file.\n");
     return 1;
     }
  else
     {
     while(fgets(buff, sizeof(buff), file) != NULL)  /* Loop until there's nothing to read
*/
    {
    BOOK book;
          /*read a line and put it in the struct */
    if(parseline(&book, buff) == 0) 
             {
             books = realloc(books, (num_books + 1) * sizeof(BOOK));
             if(!books)
                {
                /* out of memory, bale */
                books[num_books] = book;
                num_books++;
                }
             }
       }
   } // end else
    
    fclose(file); /* close file */

    for(i=0 ; i<num_books; i++) 
    { 
      printf("%s\t ", books[i].title);
      //printf(every other fields of the struct....)
    }

    if(books!=NULL) 
    {
      free(books);    /* free any allocated memory */
    }
    return 0;
}

/* Function that reads the current line of the file and puts it in an array */
int parseline(BOOK *out, const char *str)
{
  int i;

  /* stop on tab, but also on end of string or overflow so we don't crash*/
  for(i=0; str[i] != '\t' && str[i] != 0 && i < 63;i++)
     out->title[i] = str[i];
     out->title[i] = 0;

  /* return -1 on parse error */
  if(str[i] != '\t')
  return -1;

  /* for convenience, move the pointer along for the next field */
  str += i +1;

  /* now do the same thing for the other fields */

  /* 0 to indicate OK */
  return 0;
}
 
> while(fgets(buff, sizeof(buff), file) != NULL)
buff isn't allocated, so you just spray the contents of the file over random memory
Code:
char buff[BUFSIZ];
fixes this

> if(parseline(&book, buff) == 0)
No prototype in scope
Code:
int parseline(BOOK *out, const char *str);
before you try and call it.

> books = realloc(books, (num_books + 1) * sizeof(BOOK));
Two problems here
1. books is uninitialised - start with
Code:
bookInfo *books = NULL;
2. if realloc fails, all is lost.
Code:
void *temp = realloc( books, (num_books + 1) * sizeof(BOOK));
if ( temp != NULL ) {
    books = temp;
    // add new book (as you do at present)
} else {
    // existing array is safe, but unextendable
    // save data and then quit
}


> this
Code:
  for(i=0; str[i] != '\t' && str[i] != 0 && i < 63;i++)
     out->title[i] = str[i];
     out->title[i] = 0;
The indentation suggests the = 0 statement is part of the loop. It isn't.
Use braces to make your meaning clear, even if it is for just one statement.

> each bunch of 6 lines form a struct.
Your loop is OK, but you need to add two things
1. a counter which counts from 1 to 6, which identifies to parseline() the field you are processing.
2. only on the 6th iteration do you add the entry to the array.

--
 
Hey thanks a lot Salem, now I'm starting to understand a lot more ! Anyway I changed my code with your advices in mind and still have 1 small problem. When saying:

books[num_books] = bookInfo;

I get an error "illegal use of this type as an expression". Still trying to figure whats incorrect, so if you can help me with that I would be really happy ! Thanks again, here the new code:

Code:
 #include "stdafx.h"
 #include "stdio.h"
 #include <stdlib.h>
 
 /* Struct containing the informations on a book */
 struct book
 {
     char title[80];
     char autor[40];
     char editor[20];
     char ISBN[10];
     char subject[20];
     int  releaseDate;
 };
 typedef struct book bookInfo;
 
 
 int main()
 {
   char c[50];                 // Store line we read
   FILE *file;                 // File containing the data
   bookInfo *books = NULL;     // Array of books, UNKNOWN size 
   char buff[1000];         // Buffer to read in the file
   int num_books = 0;          // Keep the count of number read in
   int i, j;
   int line_number = 0;        /* Used to count the 6 lines required 
							   to create a new struct
 
   /* First step we open the file and see if it's correct */
   file = fopen("books.txt", "r");
   if(file==NULL)
      {
      printf("Error: can't open file.\n");
      return 1;
      }
   else
      {
      while(fgets(buff, sizeof(buff), file) != NULL)  /* Loop until there's nothing to read*/
        {
		/*read a line and put it in the struct */
			void *temp = realloc( books, (num_books + 1) * sizeof(bookInfo));
			if ( temp != NULL ) 
				{
				books = temp; // Set the correct size of the array containing structs
				
				/* We loop until there's 6 lines added to the struct bookInfo */
				for(line_number=0; line_number<=6; line_number++)
				{int parseline(bookInfo *out, const char *str);}
				
				books[num_books] = bookInfo; /* We add the new book (bookInfo) in the array of struct
											at the correct position only when all the fields of the
											struct are full */

				num_books++; // Increase the number of line read
				}
		  }
		} // end else
     
     fclose(file); /* close file */
 
     for(i=0 ; i<num_books; i++)
     {
       printf("%s\t ", books[i].title);
       //printf(every other fields of the struct....)
     }
 
     if(books!=NULL)
     {
       free(books);    /* free any allocated memory */
     }
     return 0;
 }
 
 /* Function that reads the current line of the file and creates struct */
 int parseline(bookInfo *out, const char *str)
 {
   int i;
 
   /* stop on tab, but also on end of string or overflow so we don't crash*/
   for(i=0; str[i] != '\t' && str[i] != 0 && i < 63;i++)
      out->title[i] = str[i];
      out->title[i] = 0;
 
   /* return -1 on parse error */
   if(str[i] != '\t')
   return -1;
 
   /* for convenience, move the pointer along for the next field */
   str += i +1;
 
   /* now do the same thing for the other fields */
 
   /* 0 to indicate OK */
   return 0;
 }
 
bookinfo is a type.
Your first post was better in this respect.
You read all your information into a temporary book
Then assign that to your array when you're done


> /* We loop until there's 6 lines added to the struct bookInfo */
for(line_number=0; line_number<=6; line_number++)
{int parseline(bookInfo *out, const char *str);}
1. This loops 7 times
2. you don't call the function at all. The loop just contains a prototype.

--
 
2. you don't call the function at all. The loop just contains a prototype."

Sorry I don't think I understand the term prototype, or at least it's meaning in this language. How do I call my function correctly then ?

So it's better to use a temp book (declared as "BOOK book;") and make the operation on this book before adding it to the array ?

 
would it be better to use linked list to conserv the structs ?
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top