problems reading struct from binary file
Web Server forum
Back To The Forum Home!Search!Private Messaging System

Web Server Talk Web Server Talk > Unix and Linux reviews > Free Unix support > Unix Programming > problems reading struct from binary file




  Last Thread   Next Thread Next
  Show Printable Version Email this Page Subscribe to this Thread      Post New Thread    Post A Reply      

    problems reading struct from binary file  
wetherbean


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
04-22-05 11:00 PM

Hey group..I was wondering if someone might be able to tell me what I
am doing wrong here..when I try to out put the string and teh int in my
struct after I read it from the binary file I create it just prints
garbage....here is my code so far

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


struct song_rec{
char* artist;
char* album;
int track;
int song_id;};

struct playlist_rec{
char* list_name;
int playlist_id;
int random;};

struct user_rec{
char* name;
int pw;};

int main(int argc,char**argv) {

FILE* user_file;
FILE* list_file;
FILE* song_file;
struct user_rec user;
int choice=0,found=0,password=0;
char* uname;


printf("1)REGISTER\n");
printf("2)LOGIN\n");
scanf("%d",&choice);


switch(choice){

case 1:
printf("Enter desired login name: ");
scanf("%s",uname);
user_file=fopen("user_file.dat","w");
fclose(user_file);
user_file=fopen("user_file.dat","r");

while(!feof(user_file)){
fread(&user,sizeof(user),1,user_file);
printf("name: %s password:
%d\n",user.name,ntohs(user.pw));
if (strcmp(uname,user.name)==0){
found=1;
printf("Login name already in use\n");
fclose(user_file);
exit(1);}
}//end while
if (found==0){
user_file=fopen("user_file.dat","a");
printf("Enter desired password: ");
scanf("%d",&password);
strcpy(user.name,uname);
user.pw=password;
fwrite(&user,sizeof(user),1,user_file);
fclose(user_file);}



break;
}
}


Thanks in advance,
wetherbean






[ Post a follow-up to this message ]



    Re: problems reading struct from binary file  
Fletcher Glenn


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
04-22-05 11:00 PM

wetherbean wrote:
> Hey group..I was wondering if someone might be able to tell me what I
> am doing wrong here..when I try to out put the string and teh int in my
> struct after I read it from the binary file I create it just prints
> garbage....here is my code so far
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
>
> struct song_rec{
>         char* artist;
>         char* album;
>         int track;
>         int song_id;};
>
>     struct playlist_rec{
>         char* list_name;
>         int playlist_id;
>         int random;};
>
>     struct user_rec{
>         char* name;
>         int pw;};
>
> int main(int argc,char**argv) {
>
>     FILE* user_file;
>     FILE* list_file;
>     FILE* song_file;
>     struct user_rec user;
>     int choice=0,found=0,password=0;
>     char* uname;
>
>
>      printf("1)REGISTER\n");
>     printf("2)LOGIN\n");
>     scanf("%d",&choice);
>
>
>      switch(choice){
>
>         case 1:
>             printf("Enter desired login name: ");
>             scanf("%s",uname);
>                 user_file=fopen("user_file.dat","w");
>                 fclose(user_file);
>                 user_file=fopen("user_file.dat","r");
>
>                  while(!feof(user_file)){
>                    fread(&user,sizeof(user),1,user_file);
>                    printf("name: %s password:
> %d\n",user.name,ntohs(user.pw));
>                    if (strcmp(uname,user.name)==0){
>                        found=1;
>                        printf("Login name already in use\n");
>                        fclose(user_file);
>                         exit(1);}
>                    }//end while
>                    if (found==0){
>                        user_file=fopen("user_file.dat","a");
>                        printf("Enter desired password: ");
>                        scanf("%d",&password);
>                        strcpy(user.name,uname);
>                        user.pw=password;
>                        fwrite(&user,sizeof(user),1,user_file);
>                        fclose(user_file);}
>
>
>
>                 break;
>             }
>         }
>
>
>    Thanks in advance,
>         wetherbean
>
Your stuct contains pointers.  Pointers are not valid things to store
as they may be different the next time you start your program.  Instead
you need put the actual data into your struct.

--

Fletcher Glenn






[ Post a follow-up to this message ]



    Re: problems reading struct from binary file  
Eric Sosman


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
04-22-05 11:00 PM



wetherbean wrote:
> Hey group..I was wondering if someone might be able to tell me what I
> am doing wrong here..when I try to out put the string and teh int in my
> struct after I read it from the binary file I create it just prints
> garbage....here is my code so far

You've got so many problems here that I lack the energy
to clean the Augean Stables.  I'll just spend time on some
of the worst spots and maybe just draw attention to a few of
the others.  "FAQ X.Y" means "Refer to Question X.Y in the
comp.lang.c Frequently Asked Questions (FAQ) list at
<http://www.eskimo.com/~scs/C-faq/top.html>."

> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
>
> struct song_rec{
>         char* artist;
>         char* album;
>         int track;
>         int song_id;};
>
>     struct playlist_rec{
>         char* list_name;
>         int playlist_id;
>         int random;};
>
>     struct user_rec{
>         char* name;
>         int pw;};
>
> int main(int argc,char**argv) {
>
>     FILE* user_file;
>     FILE* list_file;
>     FILE* song_file;
>     struct user_rec user;
>     int choice=0,found=0,password=0;
>     char* uname;
>
>
>      printf("1)REGISTER\n");
>     printf("2)LOGIN\n");
>     scanf("%d",&choice);

No success/failure check.

>      switch(choice){
>
>         case 1:
>             printf("Enter desired login name: ");
>             scanf("%s",uname);

FAQ 4.2, FAQ 12.20.


>                 user_file=fopen("user_file.dat","w");

No success/failure check.  Also, if the "user_file.dat"
contained something before the program started, it doesn't
contain it any longer: You've just blown it away.  Also
see FAQ 12.38 if you think there's any chance this program
might someday want to run on a non-POSIX system.

>                 fclose(user_file);
>                 user_file=fopen("user_file.dat","r");

No success/failure check.  FAQ 12.38.

>                  while(!feof(user_file)){

FAQ 12.2.

>                    fread(&user,sizeof(user),1,user_file);

No success/failure check.

>                    printf("name: %s password:
> %d\n",user.name,ntohs(user.pw));

You've read (or tried to read) the `user' struct, but
where does its `name' element point?  You certainly haven't
read anything it might point to.  Also, ntohs() isn't much
of an encryption scheme (and your program doesn't declare it).

>                    if (strcmp(uname,user.name)==0){
>                        found=1;
>                        printf("Login name already in use\n");
>                        fclose(user_file);
>                         exit(1);}

EXIT_FAILURE would be preferable.

>                    }//end while
>                    if (found==0){
>                        user_file=fopen("user_file.dat","a");

No success/failure check.  FAQ 12.38.

>                        printf("Enter desired password: ");
>                        scanf("%d",&password);

No success/failure check.

>                        strcpy(user.name,uname);

FAQ 4.2.

>                        user.pw=password;
>                        fwrite(&user,sizeof(user),1,user_file);

No success/failure check.

>                        fclose(user_file);}

No success/failure check.

>
>
>                 break;
>             }
>         }

Something seems to be missing here.

>
>    Thanks in advance,
>         wetherbean

Good luck!  I think you're going to need it ...

--
Eric.Sosman@sun.com






[ Post a follow-up to this message ]



    Re: problems reading struct from binary file  
John Gordon


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
04-25-05 10:53 PM

In <1114206403.315043.171110@f14g2000cwb.googlegroups.com> "wetherbean" <bje
nkin1@gmail.com> writes:

> Hey group..I was wondering if someone might be able to tell me what I
> am doing wrong here..when I try to out put the string and teh int in my
> struct after I read it from the binary file I create it just prints
> garbage....here is my code so far

> struct song_rec{
>         char* artist;
>         char* album;
>         int track;
>         int song_id;};

Declaring your strings as "char *" isn't going to work.  Declare them
like this instead:

char artist[99]; /* or whatever size you need */

>     struct playlist_rec{
>         char* list_name;
>         int playlist_id;
>         int random;};

>     struct user_rec{
>         char* name;
>         int pw;};

Same thing here.

> int main(int argc,char**argv) {

>     char* uname;

Same here.  Declaring a char pointer doesn't actually allocate any space
for the string, so when you try to read in a value and store it, there
isn't anyplace for it to go, so it gets dumped somewhere random in memory.

For now, declare all your string data like this:

char uname[99];

If you keep using C, you will eventually learn why and how to use char
pointers, but for now, use char arrays.

--
John Gordon            "It's certainly uncontaminated by cheese."
gordon@panix.com






[ Post a follow-up to this message ]



    Re: problems reading struct from binary file  
Pascal Bourguignon


View Ip Address Report This Message To A Moderator Edit/Delete Message


 
04-25-05 10:53 PM

"wetherbean" <bjenkin1@gmail.com> writes:

> Hey group..I was wondering if someone might be able to tell me what I
> am doing wrong here..when I try to out put the string and teh int in my
> struct after I read it from the binary file I create it just prints
> garbage....here is my code so far

You should consider using text files instead of binary files.

It's easy enough to use printf and scanf, and it's more portable, and
most often it's more space efficient (and speed doesn't count much
here since we're doing I/O which is 1,000,000 times slower than the
processor.

Warning: follows untested _C_ code.  Error checking should be added!


-----(gen-c-struct.el)--------------------------------------------------

(defun field-name (f) (first  f))
(defun field-type (f) (second f))

(defun generate-c-struct-declaration (name fields)
(insert (format "struct %s {\n" name))
(dolist (field fields)
(case (field-type field)
((string)
(insert (format "    %-15s " "char*")))
((char short int long float double)
(insert (format "    %-15s " (field-type field))))
(otherwise
(insert "#warning \"The following field won't be written or read.\"\n")
(insert (format "    %-15s " (field-type field)))))
(insert (format "%s;\n" (field-name field))))
(insert "};\n"))

(defun generate-c-struct-reader (name fields)
(insert (format "struct %s* %s_read(FILE* in){\n" name name))
(insert (format "  struct %s* res=malloc(sizeof(struct %s));\n" name name))
(dolist (field fields)
(case (field-type field)
((string)
(insert (format "  res->%s=string_read(out);\n" (field-name field))))
((char short int)
(insert (format "  {int buf;fscanf(out,\"%%d\",&buf); res->%s=buf;}\n"
(field-name field))))
((long)
(insert (format "  {long buf;fscanf(out,\"%%ld\",&buf);res->%s=buf;}\n"
(field-name field))))
((float double)
(insert (format "  {double buf;fscanf(out,\"%%e\",&buf);res->%s=buf;}\n
"
(field-name field))))))
(insert (format"  return(res);\n"))
(insert "}\n"))

(defun generate-c-struct-writer (name fields)
(insert (format "void %s_write(FILE* out,struct %s* that){\n" name name
))
(dolist (field fields)
(case (field-type field)
((string)
(insert (format "  string_write(out,that->%s);\n" (field-name field))))
((char short int)
(insert (format "  fprintf(out,\"%%d\\n\",that->%s);\n"
(field-name field))))
((long)
(insert (format "  fprintf(out,\"%%ld\\n\",that->%s);\n"
(field-name field))))
((float double)
(insert (format "  fprintf(out,\"%%e\\n\",that->%s);\n"
(field-name field))))))
(insert "}\n"))

(defmacro gen-c-struct (name &rest fields)
`(progn (generate-c-struct-declaration ',name ',fields)
(generate-c-struct-reader ',name ',fields)
(generate-c-struct-writer ',name ',fields)))

-----(string_io.c)------------------------------------------------------

void string_write(FILE* out,const char* string){
fprintf(out,"%d:",strlen(string));
while(*string){
switch(*string){
case '"':  fprintf(out,"\\\""); break;
case '\': fprintf(out,"\\\\"); break;
case '\n': fprintf(out,"\\n"); break;
default: fprintf(out,"%c",*string); break; }
string++;}
fprintf(out,"\n");}


char* string_read(FILE* in){
int length,i;
char* result;
fscanf(in,"%d:",&length);
result=malloc(1+length);
for(i=0;i<length;i++){
char ch=fgetc(in);
switch(ch){
case '\':
ch=fgetc(in);
switch(ch){
case '\n': result[i]='\n'; break;
default:   result[i]=ch;   break;}
break;
default:   result[i]=ch;   break;}}
result[length]='\0';
return(result);}

------(in your source.c)------------------------------------------------

/*
(progn
(load "gen-c-struct.el")
(insert "*") (insert "/\n\n")

(gen-c-struct song_rec
(artist  string)
(album   string)
(track   int)
(song_id int))

(gen-c-struct  playlist_rec
(list_name   string)
(playlist_id int)
(random      int))

(gen-c-struct  user_rec
(name string)
(pw   int)))

;; When you want to add or modify the structures, put the cursor
;; on the line above this comment and type C-x C-e.
;; It' insert the following:

*/

struct song_rec {
char*           artist;
char*           album;
int             track;
int             song_id;
};
struct song_rec* song_rec_read(FILE* in){
struct song_rec* res=malloc(sizeof(struct song_rec));
res->artist=string_read(out);
res->album=string_read(out);
{int buf;fscanf(out,"%d",&buf); res->track=buf;}
{int buf;fscanf(out,"%d",&buf); res->song_id=buf;}
return(res);
}
void song_rec_write(FILE* out,struct song_rec* that){
string_write(out,that->artist);
string_write(out,that->album);
fprintf(out,"%d\n",that->track);
fprintf(out,"%d\n",that->song_id);
}
struct playlist_rec {
char*           list_name;
int             playlist_id;
int             random;
};
struct playlist_rec* playlist_rec_read(FILE* in){
struct playlist_rec* res=malloc(sizeof(struct playlist_rec));
res->list_name=string_read(out);
{int buf;fscanf(out,"%d",&buf); res->playlist_id=buf;}
{int buf;fscanf(out,"%d",&buf); res->random=buf;}
return(res);
}
void playlist_rec_write(FILE* out,struct playlist_rec* that){
string_write(out,that->list_name);
fprintf(out,"%d\n",that->playlist_id);
fprintf(out,"%d\n",that->random);
}
struct user_rec {
char*           name;
int             pw;
};
struct user_rec* user_rec_read(FILE* in){
struct user_rec* res=malloc(sizeof(struct user_rec));
res->name=string_read(out);
{int buf;fscanf(out,"%d",&buf); res->pw=buf;}
return(res);
}
void user_rec_write(FILE* out,struct user_rec* that){
string_write(out,that->name);
fprintf(out,"%d\n",that->pw);
}


Also, instead of putting emacs lisp code in comment in a c source file
to manually  update the generated C source, one could put it in a
source.el file, and add some rules to the Makefile:

source.c:source.el
emacs -batch -load source.el

-----(source.el)--------------------------------------------------------
(load "gen-c-struct.el")
(find-file "source.c")
(erase-buffer)

(gen-c-struct song_rec
(artist  string)
(album   string)
(track   int)
(song_id int))

(gen-c-struct  playlist_rec
(list_name   string)
(playlist_id int)
(random      int))

(gen-c-struct  user_rec
(name string)
(pw   int)))

(save-buffer (current-buffer))
------------------------------------------------------------------------


(Of course, the text file format could be smarter, adding more green
bytes, with things such as lisp s-expressions (see both:
http://theory.lcs.mit.edu/~rivest/sexp.html
http://theory.lcs.mit.edu/~rivest/sexp.txt
) or even XML, which would ask for a parser.  You can have fun!).


--
__Pascal Bourguignon__                     http://www.informatimago.com/

The world will now reboot.  don't bother saving your artefacts.





[ Post a follow-up to this message ]



    Sponsored Links  




 





   All times are GMT. The time now is 06:35 PM.      Post New Thread    Post A Reply      
  Last Thread   Next Thread Next


Most Popular forums 

Forum Jump:
Rate This Thread:

Forum Rules:
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is OFF
vB code is ON
Smilies are ON
[IMG] code is OFF
 
Medical and Health forum | Computer Games Reviews | Graphics design forum

Back To The Top
Home | Usercp | Faq | Register