I am in larval stage with Python and pre-egg stage in C++, but i am trying to do my best, specially with the "Don't Repeat Yourself" principle.
I have a multichannel raw file-format to open, with a main ascii header with fields representable as strings and integers (always coded as chars padded with white spaces). The second part is N headers, with N being a field of the main header, and each of those headers has itself a lot more of text and number fields (coded as ascii) refering to the length and size of the actual 16 bit multichannel streams that compose the rest of the file.
So far, I have this working code in C++:
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <map>
using namespace std;
struct Header {
string version;
string patinfo;
string recinfo;
string start_date;
string start_time;
int header_bytes;
string reserved;
int nrecs;
double rec_duration;
int nchannels;
};
struct Channel {
string label;
string transducertype;
string phys_dim;
int pmin;
int pmax;
int dmin;
int dmax;
string prefiltering;
int n_samples;
string reserved;
};
int main()
{
ifstream edf("/home/helton/Dropbox/01MIOTEC/06APNÉIA/Samples/Osas2002plusQRS.rec", ios::binary);
// prepare to read file header
Header header;
char buffer[80];
// reads header fields into the struct 'header'
edf.read(buffer, 8);
header.version = string(buffer, 8);
edf.read(buffer, 80);
header.patinfo = string(buffer, 80);
edf.read(buffer, 80);
header.recinfo = string(buffer, 80);
edf.read(buffer, 8);
header.start_date = string(buffer, 8);
edf.read(buffer, 8);
header.start_time = string(buffer, 8);
edf.read(buffer, 8);
stringstream(buffer) >> header.header_bytes;
edf.read(buffer, 44);
header.reserved = string(buffer, 44);
edf.read(buffer, 8);
stringstream(buffer) >> header.nrecs;
edf.read(buffer,8);
stringstream(buffer) >> header.rec_duration;
edf.read(buffer,4);
stringstream(buffer) >> header.nchannels;
/*
cout << "'" << header.version << "'" << endl;
cout << "'" << header.patinfo << "'" << endl;
cout << "'" << header.recinfo << "'" << endl;
cout << "'" << header.start_date << "'" << endl;
cout << "'" << header.start_time << "'" << endl;
cout << "'" << header.header_bytes << "'" << endl;
cout << "'" << header.reserved << "'" << endl;
cout << "'" << header.nrecs << "'" << endl;
cout << "'" << header.rec_duration << "'" << endl;
cout << "'" << header.nchannels << "'" << endl;
*/
// prepare to read channel headers
int ns = header.nchannels; // ns tells how much channels I have
char title[16]; // 16 is the specified length of the "label" field of each channel
for (int n = 0; n < ns; n++)
{
edf >> title;
cout << title << endl; // and this successfully echoes the label of each channel
}
return 0;
};
Some remarks I already have to make:
- I opted to use struct because the format specification is very hardcoded;
- I didn't iterate over the main header fields because the number of bytes and types to read seemed to me rather arbitrary;
- Now that I successfully got each channel's label, I would actually create structs for each channel's fields, which by themselves would have to be stored perhaps in a map.
My (hopefully straightforward) question is:
"Should I worry about cutting corners to make this kind of code more 'Pythonic' (more abstract, less repetitive), or this is not the way things work in C++?"
Many Python evangelists (as I would be myself, because I love it) highlight its easyness to use and all that. So, I will wonder for some time if I am doing dumb things or only doing things right, but not so "automagical" because of the very nature of C++.
Thanks for reading
Helton