LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 12-13-2003, 07:33 AM   #1
skywalker27182
Member
 
Registered: Nov 2003
Posts: 35

Rep: Reputation: 15
Using 'printf' on a 'struct'


hi,
i have a C structure, say, with the following contents:

struct abc
{
int x;
char ch[16];
int y;
} mnp[4];

from a program, i get the values of struct abc mnp[1]. i enter the values as:

x = 1;
ch = "abcdef";
y = 100;
i want the values in a file, so i use fprintf. but in the file, i see the output as:

1abcdef100

i there any way i can get the values exactly as the sizes of int and char, like
x should occupy 4 bytes(size of int) in the output file, char ch[] should occupy 16 bytes, and the y should occupy 4 bytes?
i want this because, say, i have a record of all 5 employees and i want to access the details of 4th employee. i must be able to access the details using lseek = (n - 1)*sizeof record.
 
Old 12-13-2003, 07:48 AM   #2
kev82
Senior Member
 
Registered: Apr 2003
Location: Lancaster, England
Distribution: Debian Etch, OS X 10.4
Posts: 1,263

Rep: Reputation: 51
use fwrite to write out the binary representation of the data, the following example code should help
Code:
#include <stdio.h>
#include <string.h>

typedef struct {
        int x;
        char ch[16];
        int y;
} C;

int main()
{
        FILE *f=NULL;
        C c;

        c.x=1;
        strcpy(c.ch, "abcdef");
        c.y=100;

        f=fopen("filename", "w");
        fwrite(&c, sizeof(c), 1, f);
        fclose(f);

        return 0;
}
ive not tested it but it looks ok, if it doesnt work write back.
 
Old 12-13-2003, 07:53 AM   #3
dorian33
Member
 
Registered: Jan 2003
Location: Poland, Warsaw
Distribution: LFS, Gentoo
Posts: 591

Rep: Reputation: 32
Use width & precision in the format string f.ex.
Code:
fprintf(fpnt, "%4.4i%16.16s%4.4i",mnp[1].x,mnp[1].ch,mnp[1].y);
or more complicated formatting with asterisks:
Code:
fprintf(fpnt, "%*.*i%*.*s%*.*i",
                   <len_of_x_field>,<len_of_x_field>,mnp[1].x,
                   <len_of_ch_field>,<len_of_ch_field>,mnp[1].ch,
                   <len_of_y_field>,<len_of_x_field>,mnp[1].y);
where <len_of_..._field>s can be a variables also.
 
Old 12-14-2003, 10:38 PM   #4
skywalker27182
Member
 
Registered: Nov 2003
Posts: 35

Original Poster
Rep: Reputation: 15
hi kev82 and dorian33,
i tried out your methods.

kev, i saw a few junk characters in the output file like ^@^B etc, i tried opening the outfile with "a+" and by fwrite-ing one member at a time to the file, but the results were the same.

dorian, ur method worked. i didn't know this syntax, i learned something new.

thanks a lot to both of u.
 
Old 12-15-2003, 07:30 AM   #5
kev82
Senior Member
 
Registered: Apr 2003
Location: Lancaster, England
Distribution: Debian Etch, OS X 10.4
Posts: 1,263

Rep: Reputation: 51
by skywalker27182
i there any way i can get the values exactly as the sizes of int and char, like
x should occupy 4 bytes(size of int) in the output file, char ch[] should occupy 16 bytes, and the y should occupy 4 bytes?


thats what my method did, if you run hexdump on the file produced then you will see something like
Code:
00000000  01 00 00 00 61 62 63 64 65 66 00 42 5e 83 04 08
00000010  18 2e 13 42 64 00 00 00
00000018
the black numbers are offsets from start of file, blue is first integer, red is the 16 byte character array, and green is the second integer. if you want to read the data back into the program then simply declare enough memory and use fread() if you do want your data stored in ASCII form in the file then do as dorian33 said but its a big pain in the ass to read it back in. thats why binary files are so popular.

Last edited by kev82; 12-15-2003 at 07:32 AM.
 
Old 12-15-2003, 11:40 AM   #6
skywalker27182
Member
 
Registered: Nov 2003
Posts: 35

Original Poster
Rep: Reputation: 15
so the junk characters won't make any difference? i can still read the data with open, lseek and read, right?
 
Old 12-15-2003, 12:59 PM   #7
h/w
Senior Member
 
Registered: Mar 2003
Location: New York, NY
Distribution: Debian Testing
Posts: 1,286

Rep: Reputation: 46
maybe i didnt get your question right, but ...
when u frprintf, cant you append a '\0' or a '\n' to your variables, and make it look like
Code:
1
abcdef
4
?
then you can read your file in a loop based on '\n' or '\0'.
also, since you have 2 ints there, cant u just put those two in a struct of their own, and then just have the char array as the other element?

i fail to remember, but are nested structs allowed in C (im thinking it is)?
 
Old 12-15-2003, 01:06 PM   #8
kev82
Senior Member
 
Registered: Apr 2003
Location: Lancaster, England
Distribution: Debian Etch, OS X 10.4
Posts: 1,263

Rep: Reputation: 51
by skywalker27182
so the junk characters won't make any difference?

there not junk characters, they are the ascii representation of your data in binary form.

im not sure why you wish to use open/read/write when you have C-standard streams available but you can use fopen, fread, fwrite, fseek, fclose or their unistd.h alternatives to work with and move through binary files, check out the man pages or any good book on C. if your still stuck with the idea of binary files i'll write you an example program when i get back home on wednesday.
 
Old 12-17-2003, 03:36 AM   #9
skywalker27182
Member
 
Registered: Nov 2003
Posts: 35

Original Poster
Rep: Reputation: 15
pls do include a sample program kev82. thanks.

h/w, i have a record of, say, a 100 employees of a company and the details are name, id, salary etc. it becomes a lot easier to open the record file and go to the nth employee using lseek and reading the rest of the line if all lines of the file are of same size. if it isn't i have to hunt for the right employee number, which might be same as the salary. i hope i made it clear
 
Old 12-18-2003, 08:50 AM   #10
kev82
Senior Member
 
Registered: Apr 2003
Location: Lancaster, England
Distribution: Debian Etch, OS X 10.4
Posts: 1,263

Rep: Reputation: 51
ok here ya go, the file format is quite simple, first it saves the number of records in the file(a 4-byte integer) then its just all the records one after another

code to create the file
Code:
#include <stdio.h>

typedef struct {
        int a;
        char b[16];
        int c;
} D;

int main()
{
        FILE *f=NULL;
        D *data=NULL;
        int n;
        int numEmployees=0;

        f=fopen("filename","w");

        printf("How many records?\n");
        scanf("%i", &numEmployees);

        fwrite(&numEmployees, sizeof(int), 1, f);

        for(n=0;n<numEmployees;n++) {
                D temp;

                printf("first integer?\n");
                scanf("%i", &temp.a);

                printf("character string?\n");
                scanf("%s", temp.b);

                printf("second integer?\n");
                scanf("%i", &temp.c);

                fwrite(&temp, sizeof(D), 1, f);
        }

        fclose(f);
        return 0;
}
~
code to read the file back
Code:
#include <stdio.h>

typedef struct {
        int a;
        char b[16];
        int c;
} D;

int main()
{
        FILE *f=NULL;
        int numRecs=0;
        int rec=0;
        D data;

        f=fopen("filename","r");
        fread(&numRecs, sizeof(numRecs), 1, f);

        while(1) {
                printf("file has %i records(0-%i) which one to look at?", numRecs, numRecs-1);
                scanf("%i", &rec);
                if(rec<0) break;

                fseek(f, sizeof(int)+rec*sizeof(D), SEEK_SET);
                fread(&data, sizeof(D), 1, f);

                printf("first integer %i, character string %s, second integer %i\n", data.a, data.b, data.c);
        }

        fclose(f);
        return 0;
}
~
i havnt programmed in C for a while so ive probably done something wrong but it seems to work. it needs A LOT of error checking code added if you wanted to use it for anything other than demonstration purposes.

instead of using streams you could quite as easily use open, close, read,write,lseek i dont think it makes any difference to the program.

you might consider using mmap() to access your records all the seeking would be done automatically for you and it would make adding/deleting records much easier.

Last edited by kev82; 12-18-2003 at 08:53 AM.
 
Old 12-20-2003, 12:06 PM   #11
ananthbv
Member
 
Registered: Nov 2003
Posts: 49

Rep: Reputation: 15
thanks once again, kev82, i understand it much better now! it is simple yet elegant.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
g++ and wrong struct member addresses / struct size misreporting sonajiso Linux - General 5 05-22-2004 10:16 PM
switch statement converting struct char to struct int oceaneyes2 Programming 2 12-10-2003 04:30 PM
using struct type X as pointer in struct X. worldmagic Programming 1 10-28-2003 02:06 PM
Accessing a struct inside struct cxel91a Programming 1 09-17-2003 04:24 PM
printf new_user10 Programming 3 09-09-2003 11:12 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:17 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration