Re: File handling

Jens.Toerring_at_physik.fu-berlin.de
Date: 01/31/05


Date: 31 Jan 2005 13:13:10 GMT

Chathu <chuthurika@gmail.com> wrote:
> I have a problem on retriving a content of a binary file I wrote into.
> My program user structures, dynamic allocation of memory and files. I
> take the infomation into a dynamicaly allocated structure and then
> write it to a binary file using fwrite() with appending mode. I can
> retrive the data I wrote while the program is running. But if I stop
> the program and re-execute it I can't read the things I wrote to the
> file last time(only some vieard characters appear), but the the data I
> wrote this time appeard without any problem.
> How can I retrive the data I wrote to the file previousy.
> Souce code of the program I wrote is as follows,

Since there are that many errors in this program I mostly restrict
my comments to the first occurence of an error...

> #include<stdio.h>
> #include<conio.h>
> #include<malloc.h>

Both <conio.h> and <malloc.h> aren't standard C header files. Replace
<malloc.h> with <stdlib.h>. I have no idea what <conio.h> is supposed
to do.

> #include<string.h>
> #include<ctype.h>

> typedef struct student{
> char *name;
> int age;
> }stu;

> void stu_initializer(stu *p,FILE *fp);
> void print_stu(stu *p, FILE *fp);

> void main()

main() is always supposed to return an int. And it has either zero
or two arguments, so make that

int main( void )

(or

int main( int argc, char *argv[ ] )

in case you are interested in the command line arguments).

> {
> clrscr();

What's that supposed to do? It's not a standard C function.

> stu *p;
> FILE *fp;

Unless you have a C99 compliant C compiler all variable definitions
mus come before the first executable statement.

> //allocate memory for the structure

Please use normal C style comments, i.e. '/*' and '*/', when you
post in newsgroups. The C++ style comments were only introduced
with the new C99 standard and often make it hard to see where a
comment ends when a newsreader wraps long lines.

> p=(stu*)malloc(sizeof(stu));

1) Check the return value of malloc().
2) Drop the cast. It's not needed and will keep the compiler from
   complaining when you forgot to include the header file where
   malloc() is declared in (i.e. <stdlib.h>).

> fp=fopen("stu.dat","a+b");

Check the return value of fopen().

> stu_initializer(p,fp);

There's no declaration of this function (the definition only comes
later), so the compiler can't check if you call it with the correct
arguments,

> fclose(fp);

> clrscr();
> fp=fopen("stu.dat","rb");
> print_stu(p,fp);

Again no declaration for the function...

> fclose(fp);
> free(p);
> }////end main

Since main() must return an integer you're missing a return statement
here.

> /////////////////////////////////////////////////////////////////////
> //set the information about the parties
> void stu_initializer(stu *p,FILE *fp)
> {
> int a;
> char buffer[81];

> do{clrscr()

> printf("Enter the student name: ");

Unless the line ends with a '\n' it usually isn't printed immediately.
You need a 'fflush(stdout);' after this.

> gets(buffer); fflush(stdin);

Now, that's really horrible. First of all. Never, ever use gets().
There is no way to keep the user from entering more character
than fit into the buffer gets() puts them in. The function is
broken by design. Use fgets() instead.

Second, you can't fflush() stdin, you can only fflush() output
channels.

> //alocate memory for the stu name inside the structure

> p[0].name=(char*)malloc((strlen(buffer)+1)*sizeof(char));

sizeof(char) is 1 by definition. And why do you use 'p[0]' here?
Since 'p' isn't an array it would be clearer to use 'p->name'.

> strcpy(p[0].name,buffer);//copy the name to the structure

> //age of the student
> printf("\nEnter the index of the stu? ");
> scanf("%d",&p[0].age);

Don't use scanf() when reading user input - if what the user enters
isn't an integer you will get rather starnge results. Use fgets() to
get the whole stuff and then use e.g. sscanf() to get the value,
giving you a chance to check if there was an integer at all.

> fflush(stdin);
> //write to the file
> fwrite(p,sizeof(*p),1,fp);

Now you try to write a structure, containing a pointer to a string.
Once you read back in the file what the pointer points to is rather
likely not the string that was at that address before. You have to
write the string itself into the file, not just a pointer to were
that string was sometime in the past. You might get away with that
here by accident since you read back the structures within the same
program (and since you never deallocate the memory for the strings
once they aren't used anymore), but never if you try to read them
back from a file in a newly started program.

Moreover, you only write out as many bytes as a pointer to such a
structure has because of the '*' in front of 'p'. But if you want
to write out the structure you must fwrite() as many bytes as the
structure is long.

> printf("\n\nAny more students?[Y][N] ");
> }while(toupper(getch())=='Y');

getch() isn't standard C function, so I can't see if this here is
correct...

> clrscr();
> fflush(stdin);//clear the input buffer

No, you clear the input buffer by reading until nothing is in
there anymore.

> }//end function

> /////////////////////////////////////////////////////////////////////
> //print the stu list
> void print_stu(stu *p, FILE *fp)
> {
> printf("%s %s \n","Name","Age");
> while((fread(p,sizeof(*p),1,fp))==1)

This won't work for the multiple reasons given above.

> printf("%s %d\n",p[0].name,p[0].age);
> }

As a rule writing out structures in binary form is a bad idea. Even
if you get it right it will only work in case you read back the file
on a machine with the same archtitecture and may require to have the
programs for writing and reading where compiled with the same com-
piler.
                                    Regards, Jens

-- 
  \   Jens Thoms Toerring  ___  Jens.Toerring@physik.fu-berlin.de
   \__________________________  http://www.toerring.de


Relevant Pages

  • Re: finding how much the file system is full, from a C program?
    ... If string is a null pointer, the system function determines whether the host ... The fopen function opens the file whose name is the string pointed to by filename, and associates a stream with it. ... wb truncate to zero length or create binary file for writing ...
    (comp.lang.c)
  • Re: Problem in writing structure to Binary file in C lang
    ... reading those data from binary file and display it in C language. ... How should the program know the size of the string without actually ... but not the string pointed to by the structure, it also writes a binary pointer to ...
    (comp.lang.c.moderated)
  • Re: Interesting problem: serializing in with MFC CArchive, reading out using C# BinaryReader
    ... I solved it by looking into the MFC ... public string ReadCString() ... >> I am able to open the binary file and read out the individual ... >> old string termination issues, but I've checked the byte representing ...
    (microsoft.public.dotnet.languages.csharp)
  • RE: Speed of Applications in VBA vs VB
    ... I dont think there are any cr lf in the binary file but I'm learning a lot ... Dim filebuffer As String ... I will try the streamreader. ... functionality around the VBA engine that is not available in VBA (creating ...
    (microsoft.public.excel.programming)
  • Re: Copying byte sequence from integer/real to character array
    ... > I am writing code to write a binary file. ... > I therefore want to create a large character array, ... later you can read the file substituting a binary read (without format ... I wrote a routine that allows creating a big string of any ...
    (comp.lang.fortran)