I have a struct like that
struct Data {
int ID;
double test_sample[2065][1];
int XX_row;
int XX_col
double **XX; //size=[2065][changing]
double **alpha_new; //size=[changing][1]
int alpha_new row;
int alpha_new_col;
double t3;
double kernel_par;
}person[20];
I've written this struct for every person (for 20 person) into 20 file using fwrite
:
fwrite(&person, sizeof( struct Data ), 1,Ptr );
Now I have 20 files in binary. Each file includes these variables for one person. All is Ok for now.
Problem: I can't read a file and assingn it to a struck because in every file, dimension of XX and alpha_new Matrix is different. (in a file [2065][8],some of them[2065][12])
I need to read these variables using fread
(or different) and input to the face recognition program...
Is there a way to read variables individually in the file or should I change the writing method as well?
I don't know how to write all variables matrixes in one file without using struct!
I hope I can explain my problem here, sorry for my poor english, I waiting for your help to finish my Final project in c; I am using visual studio 2012
For such a complex structure, it's a modestly major undertaking. Here's a not-so-short SSCCE (Short, Self-Contained, Complete Example). There are really 3 files slammed into one:
stderr.h
— declarations of error reporting functions (top 10 lines)serialize.c
— the serialization code (just under 300 lines in between)stderr.c
— the error reporting functions (bottom 40 lines)I'm not planning to explain the error reporting functions. They work more or less like
printf()
as far as formatting arguments goes, but they write to standard error, not standard output, and they include the program name as a prefix, and the error derived fromerrno
. Theemalloc()
function checks memory allocations, reporting an error and exiting if the allocation fails. This error handling is adequate for simple programs; it is not adequate for complex programs that need to recover if there's a memory problem, saving the work or whatever.Within the real serialization code, there are 4 groups of functions, plus
main()
to orchestrate.The print functions allow a human to see the data, and you could save the output to file and compare the export data with the import data to ensure that they're the same.
The code would be simpler if you used a structure to describe all your 2D arrays, such as:
You'd then simply embed 3 of these into your
struct Data
:I'm really not clear what the benefit of
double test_sample[2065][1];
is compared withdouble test_sample[2065];
. I will observe it makes the code more complex than it would be otherwise. I end up treating it as a normal 1D array ofdouble
by using&data->test_sample[0][0]
as the starting point.There's more than one way to do the serialization. I've opted for a 2D array of doubles to be represented by N 1D arrays, and each 1D array is prefixed by a
size_t
describing the size of the 1D array. That gives some redundancy in the files, which means that there's slightly better error detection. It would be feasible to simply output the two dimensions of a 2D array, followed by rows x cols values. Indeed, at one point, I had the import code assuming that while the export code was using the other technique — this did not make for a happy runtime when the numbers were misunderstood and I was getting debug output and errors like:That's a lot of memory...the 2.470328e-323 was a symptom of trouble, too. (So no, I didn't get it all right on the first time I ran the code.)
I did most of the testing with SAMPLE_SIZE at 5 and NUM_PERSON at 3.
serialize.c
When run under
valgrind
, it was given a clean bill of health with no memory leaked. And it took more than one pass before I could safely say that, too (valgrind
showed up a bug that eyeballing the results hadn't spotted, though it was obvious once detected).Answers to questions in comments
Or, since you are probably on Windows and using MSVC:
double **data = (double **)emalloc(rows * sizeof(*data));
_snprintf()
andsnprintf_s()
and so on in MSDN. I find it via Google with 'site:microsoft.com snprintf' (for various spellings of 'snprintf') when I need to know what MSVC does.In case of emergency, use
sprintf()
; the size of the buffer is big enough that there shouldn't be any risk of overflow, which is whatsnprintf()
et al protect against.cernel_matrix()
function isn't told how big the matrices are, so I don't know how it can possibly work reliably.test_sample
tocernel_matrix
is safe; adouble matrix[][1]
value does not convert todouble **
. So I'm not convinced I understand whytest_sample
is a matrix like that.I put together a micro test-case for this:
The compiler told me:
The 'uninitialize' warning is perfectly valid, but the problem is the other warning and its note. You should be getting something similar from your compiler.
When someone else provides you with code because you've not shown anything, you run the risk of not understanding what they do.
Since you need to understand the code to present it to the teachers, you're probably going to need to do some programming exercises. Note that one of the first things I did was cut the problem down to toy size (instead of 2065, I used 5 or 10 or 20). You should do the same. Start with a structure that only contains the fixed size elements —
id
,t3
,kernel_par
andtest_sample
. Make it so that you can initialize and export and import that. You can import into a different variable than the one you export, and then do a comparison of the two variables. You could even omittest_sample
in the first version.When you've got that working, then add one of your arrays and its dimension members. Now get that working (with size 4x5 or similar). Then add the other array (it should be trivial). As you do this, you should see what the various functions in the example I gave do, and why they're there. They're all 'necessary' at some level. As I alluded in my comments, it took me several (too many) attempts to get it right. I was compiling with rigorous warning options, but still
valgrind
was wittering about uninitialized data (as I was about to post). But I eventually spotted an incompletely edited copy'n'paste piece of code.Note that if you'd posted code that did a sane job of attempting to export the data, and preferably a sane job of attempting to import the data, then that code could have been fixed. Since you posted no code of any worth whatsoever, it made it hard to produce code that addressed your real problem without producing something testable. The code I provided is testable. The testing could be more comprehensive — yes, undoubtedly. But making code testable, and testing it, is an important part of learning to program.
Incidentally, the key point in the export process for variable length data of any type (such as arrays) is to make sure the size of the data (array) is written before the data (array) itself is written. Then the import process knows how much space to allocate before reading the data (array) back in.