0

Can someone tell my why won't this function work? I just can't get it...

void writeRegister(FILE *arq, Book *L){ //writes in actual file position
  char c = '|';
  int sizeRegWrite = reglen(L); //reglen() returns the size of Book
  fwrite(&sizeRegWrite, sizeof(int), 1, arq);

  fwrite(L->TITLE, sizeof(char), strlen(L->TITLE), arq);
  fwrite(&c, sizeof(char), 1, arq); //writing delimiter

  fwrite(L->AUTHOR, sizeof(char), strlen(L->AUTHOR), arq);
  fwrite(&c, sizeof(char), 1, arq); //writing delimiter

  fwrite(L->PUBLISHER, sizeof(char), strlen(L->PUBLISHER), arq);
  fwrite(&c, sizeof(char), 1, arq); //writing delimiter

  fwrite(L->YEAR, sizeof(int), 1, arq);
  fwrite(&c, sizeof(char), 1, arq); //writing delimiter

  fwrite(L->LANGUAGE, sizeof(char), strlen(L->LANGUAGE), arq);
  fwrite(&c, sizeof(char), 1, arq); //writing delimiter

  fwrite(L->PAGES, sizeof(int), 1, arq);
  fwrite(&c, sizeof(char), 1, arq); //writing delimiter

  fwrite(L->PRICE, sizeof(float), 1, arq);
  fwrite(&c, sizeof(char), 1, arq); //writing delimiter
        return;
}  

The struct Book is declared like this:

typedef struct {
    char *TITLE;
    char *AUTHOR;
    char *PUBLISHER;
    int YEAR;
    char *LANGUAGE;
    int PAGES;
float PRICE;
} Book;

Main

int main() {
FILE *arq = fopen("BD_books2.bin", "rb+");
if(arq == NULL)
    printf("Error while opening file!!!");

Book L;
readData(&L); //Reads all fields from keyboard and places in Book. Working properly
writeRegister(arq, &L);

system("pause");
return 0;

}

I have to use those pointers inside the struct, so I can't remove them. By the way, my problem is only with those integers and the float.

This fuction is only working properly if I write all the integers and floats (YEAR, PAGES and PRICE) with fprintf(), but I'm writing it in a binary file, and of course I want to write it in binary, so I'm trying to use fwrite().

Another thing is: the compiler is pointing incompatible type for argument 1 of 'fwrite' at this line: fwrite(L->PRICE, sizeof(float), 1, arq);

Can someone explain me what is happening? My program crashes when it tries to write in the file...

9
  • The inconveniently omitted readData and reglen may well play in to this. Any reason in particular you chose not to include them, if for no other reason than to finish the MCVE? Commented Jun 1, 2015 at 4:34
  • BTW: Rather than fwrite(&sizeRegWrite, sizeof(int), 1, arq);, consider the model fwrite(&var, sizeof var, 1, arq); Commented Jun 1, 2015 at 4:41
  • 1
    Parsing the resulting file sounds like a complete nightmare; you mix binary data with ASCII delimiters. May I suggest either sticking with a text format (using fprintf to write each line and fscanf to read the file) or a more structured binary format (like length-prefixed strings)? Commented Jun 1, 2015 at 4:46
  • 'L' is a reserved numeric modifier in C, suggest using meaningful name, like 'myBook' Commented Jun 3, 2015 at 16:59
  • in the main() function, when the fopen() fails, output the error message (suggest using perror()) then exit the program, Do Not continue execution, as if the fopen() were successful Commented Jun 3, 2015 at 17:06

4 Answers 4

7

The first parameter of fwrite expects a pointer.

Lines such as the following:

fwrite(L->PAGES, sizeof(int), 1, arq);

Should be written as follows:

fwrite(&(L->PAGES), sizeof(int), 1, arq);

Sames goes for YEAR and PRICE members of that struct

fwrite(&(L->YEAR), sizeof(int), 1, arq);
...
fwrite(&(L->PRICE), sizeof(float), 1, arq);

Note, you don't need to make the same change for TITLE, PUBLISHER, and AUTHOR because the type of those member fields are already pointers (char*).

Sign up to request clarification or add additional context in comments.

Comments

3

The signature of fwrite is

std::size_t fwrite( const void* buffer, std::size_t size, std::size_t count, std::FILE* stream );

The first argument to the function needs to be a pointer. I am surprised you didn't get compiler errors with the following lines.

fwrite(L->YEAR, sizeof(int), 1, arq);
fwrite(L->PAGES, sizeof(int), 1, arq);
fwrite(L->PRICE, sizeof(float), 1, arq);

They need to be

fwrite(&(L->YEAR), sizeof(int), 1, arq);
fwrite(&(L->PAGES), sizeof(int), 1, arq);
fwrite(&(L->PRICE), sizeof(float), 1, arq);

Also, it is a good practice to check the return values of all IO functions to make sure that they work as you expect them to.

if ( fwrite(&(L->YEAR), sizeof(int), 1, arq) != 1 )
{
   // Deal with the error condition.
}

2 Comments

@ R Sahu - Thank you for your answer! Sadly, I can't pick 2 answers as the best one...
@Quik19, that's alright. You got the needed answer. That's the most important part.
1

You must pass the address of L->YEAR to fwrite

fwrite(L->YEAR, sizeof(int), 1, arq);

fwrite(&(L->YEAR), sizeof(int), 1, arq);

Comments

0

the following code:

1) eliminates the bad practice of typedef'ing a struct
2) removed the mis-leading all caps of the struct field names
3) contains the needed #includes
4) contains the needed prototypes for the external (in another file) functions
5) checks for the worst of the many possible runtime errors
6) replaces the mis-leading 'L' with a meaningful name
7) modifies the file pointer variable to a commonly known name

suggest compiling with all warnings enabled (and fix the warnings)
for gcc, at a minimum, use '-Wall -Wextra -pednatic'


#include <stdio.h>
#include <stdlib.h>
#include <string.h>



struct Book
{
    char *title;
    char *author;
    char *publisher;
    int   year;
    char *language;
    int   pages;
    float price;
};

int reglen( struct Book * );
int readData( struct Book * );


void writeRegister(FILE *fp, struct Book *myBook)
{ //writes in actual file position
    char c = '|';
    int sizeRegWrite = reglen(myBook); //reglen() returns the size of Book
    fwrite(&sizeRegWrite, sizeof(int), 1, fp);

    fwrite(myBook->title, sizeof(char), strlen(myBook->title), fp);
    fwrite(&c, sizeof(char), 1, fp); //writing delimiter

    fwrite(myBook->author, sizeof(char), strlen(myBook->author), fp);
    fwrite(&c, sizeof(char), 1, fp); //writing delimiter

    fwrite(myBook->publisher, sizeof(char), strlen(myBook->publisher), fp);
    fwrite(&c, sizeof(char), 1, fp); //writing delimiter

    fwrite(&(myBook->year), sizeof(int), 1, fp);
    fwrite(&c, sizeof(char), 1, fp); //writing delimiter

    fwrite(myBook->language, sizeof(char), strlen(myBook->language), fp);
    fwrite(&c, sizeof(char), 1, fp); //writing delimiter

    fwrite(&(myBook->pages), sizeof(int), 1, fp);
    fwrite(&c, sizeof(char), 1, fp); //writing delimiter

    fwrite(&(myBook->price), sizeof(float), 1, fp);
    fwrite(&c, sizeof(char), 1, fp); //writing delimiter
    return;
} // end function: writeRegister


int main( void )
{
    FILE *fp = fopen("BD_books2.bin", "rb");
    if(fp == NULL)
    {
        perror( "fopen for BD_books2.bin failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, fopen successful

    struct Book myBook;
    int goodRead = readData(&myBook); //Reads all fields from keyboard and places in Book. Working properly
    if( goodRead )
    {
        writeRegister(fp, &myBook);
    }

    system("pause");
    return 0;
} // end function: main

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.