No i've been googling for some time now and im yet to find a solution for this problem. I have a structure that has set variable that i need to store information to a file. Can someone tell me the easiest way to approach this?
No i've been googling for some time now and im yet to find a solution for this problem. I have a structure that has set variable that i need to store information to a file. Can someone tell me the easiest way to approach this?
See the man pages of the block I/O functions: fread() and fwrite().
Google "serialization".
This may help:
SourceForge.net: Serialization - cpwiki
I wrote that, so it must be good.
C programming resources:
GNU C Function and Macro Index -- glibc reference manual
The C Book -- nice online learner guide
Current ISO draft standard
CCAN -- new CPAN like open source library repository
3 (different) GNU debugger tutorials: #1 -- #2 -- #3
cpwiki -- our wiki on sourceforge
I think "stream vs. binary" is ambiguous, perhaps that is derived from the use of C++ operators? After all, there is such a thing as a binary or bit stream, but I presume you mean a "text stream".
Anyway, yes it was intentional, but I just re-read it myself, lol, and you're right, it is slightly misleading that way, so I changed some of the text (eg, it now says, "Often serialized data files cannot be read as normal text in a file browser or editor, since the typed (ints, structs, etc) data need not be translated into strings. However, there are formal schemas for serialization (such as XML or JSON) that are based on such a translation; these are not much discussed here. "
I am curious about the origin of that quote "Programmer (noun): An organism that can turn caffeine and alcohol into code". I'm sure it was actually laserlightAlso...nice uncyclopedia link!
C programming resources:
GNU C Function and Macro Index -- glibc reference manual
The C Book -- nice online learner guide
Current ISO draft standard
CCAN -- new CPAN like open source library repository
3 (different) GNU debugger tutorials: #1 -- #2 -- #3
cpwiki -- our wiki on sourceforge
Yes....I presume you mean a "text stream"
My point was that.. your block copying/dumping of memory could give interesting results when used with floating points.
Not if they are read in and out as floats, and the endianness is the same. As long as there are no pointers involved, you can write/transmit any C type out, including arrays and structs, arrays of structs, etc, and easily read them directly back in again (presuming you use the same types again).
There is a potential complication with struct padding, of course.
C programming resources:
GNU C Function and Macro Index -- glibc reference manual
The C Book -- nice online learner guide
Current ISO draft standard
CCAN -- new CPAN like open source library repository
3 (different) GNU debugger tutorials: #1 -- #2 -- #3
cpwiki -- our wiki on sourceforge
this is what i have i followed the cprogramming tutorial doesn't build though
Code:#include <stdio.h> #include <stdlib.h> typedef struct { char p_name[10]; int age; } records; int main (void) { FILE *fp; fp=fopen("test.bin", "wb"); printf("Enter a name: \n"); scanf("%s", &records.p_name); printf("Enter an age: \n"); scanf("%d", &records.age); fwrite(name, sizeof(p_name),1, fp); fwrite(name, sizeof(age), 1, fp); }
Here's a confusing thing about typedefs...this:
Defines a single instance of a struct called "whatever". But this:Code:struct { } whatever;
Defines a new type called "whatever", but not any instance of it. So with your code, you can either get rid of "typedef" or (preferably, IMO), declare an instance of type records:Code:typdef struct { } whatever;
So now you have an instance of type records called "test". That means you have to change "records" to "test" in main(); "records" is the typename, "test" is the actual variable.Code:records test;
In either case, you cannot refer to a member of a struct without the instance name, which you do in the two fwrite() calls. You need to use "records.age" (or "test.age") everytime.
Finally, records.p_name in your original code is an array, so it counts as a pointer for scanf() -- you should not use & there. But you do need & with record.age in the fwrite, because the first arg to fwrite is a pointer.
C programming resources:
GNU C Function and Macro Index -- glibc reference manual
The C Book -- nice online learner guide
Current ISO draft standard
CCAN -- new CPAN like open source library repository
3 (different) GNU debugger tutorials: #1 -- #2 -- #3
cpwiki -- our wiki on sourceforge
@teensicle... The others are giving you very good advice about the creation and use of your struct, listen to them carefully.
For my part in this I offer you the following demonstration program that uses a near identical struct... From my code word could be name and number could be age... so this is very like what you are probably trying to do. Pay paticular attention to how the records (structs) are written to and read from the data file... Copy and compile the program and run it to give yourself a demonstration of how it works... but don't even think about handing my code in as homework, it's been posted several times in a couple of different places so you'll just get yourself in trouble for cheating. However, if you follow the techniques used, you can finish your program.
Code://random access file demo #include <stdlib.h> #include <stdio.h> #include <time.h> #include <ctype.h> #include <string.h> #define FNAME "random.dat" // test data struct struct t_Record { int number; char word[16]; } Record; /////////////////////////////////////////////////////// // Random Access File Handlers // // open or create the file FILE *FileOpen(char* Filename) { FILE* pFile; pFile = fopen(Filename,"rb+"); if (!pFile) pFile = fopen(Filename,"wb+"); return pFile; } // Write a record to the file int WriteRecord(FILE *File, int RecNum) { if( fseek(File, RecNum * sizeof(Record), SEEK_SET) == 0 ) if ( fwrite(&Record,sizeof(Record),1,File) ) return 1; return 0; } // read a record from the file int ReadRecord(FILE *File, int RecNum) { if( fseek(File, RecNum * sizeof(Record), SEEK_SET) == 0 ) if ( fread(&Record,sizeof(Record),1,File) ) return 1; return 0; } // add a new record to the file int AddRecord(FILE *File) { fseek(File,0,SEEK_END); fwrite(&Record,sizeof(Record),1,File); return (ftell(File) / sizeof(Record)) - 1; } ////////////////////////////////////////////////////////////// // View a Record // int ViewRecord (FILE *File, int RecNum) { if (! ReadRecord(File,RecNum)) { printf("Invalid record\n"); return -1; } printf("-----\n"); printf("Record : %d\n",RecNum); printf("Number Value : %d\n",Record.number); printf("Word Value : %s\n",Record.word); printf("-----\n"); return RecNum; } ////////////////////////////////////////////////////////////// // Add a new record // int AddNewData(FILE *File) { memset(&Record,0,sizeof(Record)); printf("\nEnter a number : "); scanf("%d", &Record.number); printf("Enter a word : "); scanf(" %s",Record.word); return AddRecord(File); } ////////////////////////////////////////////////////////////// // Edit a record // int EditRecord(FILE *File, int RecNum) { if (! ReadRecord(File,RecNum)) { printf("Invalid record\n"); return -1; } printf("\n-----\n"); printf("Record : %d\n",RecNum); printf("Number Value : %d\n",Record.number); printf("Word Value : %s\n",Record.word); printf("-----\n"); do { while(getchar() != '\n'); printf("Change Values: Number, Word or Save (N, W or S) ? "); switch (toupper(getchar())) { case 'N' : printf("\nEnter new number : "); scanf("%d",&Record.number); break; case 'W' : printf("Enter new word : "); scanf(" %15s", Record.word); break; case 'S' : if (WriteRecord(File,RecNum)) printf("\nRecord #%d updated\n",RecNum); return RecNum; } } while(1); return -1; } //////////////////////////////////////////////////////////////// // List records // void ListRecords(FILE *File ) { int i = 0; printf("\nRecord Number\tWord\n\n"); while (ReadRecord(File,i)) { printf("%3d%16d\t%s\n",i,Record.number,Record.word); i++; } printf("\n\n"); } //////////////////////////////////////////////////////// // this is for demonstration purposes only // you would not do this in a real program void InitFile(FILE* File) { int x, y; memset(&Record,sizeof(Record),0); for (x = 0; x < 10; x++) { Record.number = rand(); for (y = 0; y < ((Record.number % 15) + 1); y++) Record.word[y] = (rand() % 26) + 'a'; Record.word[y] = 0; if (! WriteRecord(File,x)) printf("Oh drat!"); } } ////////////////////////////////////////////////////////// // program mains // int main (void) { int Rec = 0; // record number FILE *File; srand(time(NULL)); File = FileOpen(FNAME); if (!File) { printf("Curses foiled again!\n\n"); exit(-1); } printf("Random Access File Demonstration\n\n"); do { printf("Menu : Dummy, Add, Edit, View, List, Quit (D, A, E, V, L or Q) : "); switch(toupper(getchar())) { case 'D' : printf("Creating dummy file of 10 entries\n"); InitFile(File); break; case 'A' : Rec = AddNewData(File); printf("Record #%d Added\n\n", Rec); break; case 'E' : printf("\nRecord number (-1 Cancels): "); scanf("%d",&Rec); if (Rec > -1) EditRecord(File,Rec); break; case 'V' : printf("\nRecord number (-1 Cancels): "); scanf("%d",&Rec); if (Rec > -1) ViewRecord(File,Rec); break; case 'L' : ListRecords(File); break; case 'Q' : fclose(File); return 0; } while(getchar() != '\n'); } while (1); return 0; }
Last edited by CommonTater; 11-13-2011 at 01:13 PM.
@MK27 and @Commontater i really get what your saying and will modify the code!
@Commontater and @MK27 dudes you guys rock!