I have been trying to do a function that can read in a certain type of file, this file contains data on genptypes and therefore has a number of columns with single letters denoting the genotype (the take away message is that these are chars).
So therefore I have created this struct that can store this type of file:
1 2 3 4 5 6 7 8 9 10 11 12
typedefstruct{
char** familyID;
char** individualID;
char** paternalID;
char** maternalID;
int* sex;
double* phenotype;
char** genotypes;
int sites;
int individuals;
}pFile;
In order to store all these chars, I thought of creating a matrix for them, as I have n lines with m chars. So I am used to this approach of a pointers to an array of pointers, which I have done previously for double and int. Like this:
But then when I try and allocate this matrix I get this error:
1 2 3 4 5 6 7 8 9 10 11
ped.genotypes = allocChar(lines,columns-6); (LINE 148)
==2536== Invalid read of size 8
==2536== at 0x401060: dallocChar (readPlink.cpp:36)
==2536== by 0x401060: dallocPFile(pFile&) (readPlink.cpp:90)
==2536== by 0x400D6D: main (readPlink.cpp:250)
==2536== Address 0x5a234a0 is 0 bytes after a block of size 80 alloc'd
==2536== at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2536== by 0x40148C: allocChar (readPlink.cpp:25)
==2536== by 0x40148C: readPFile(char const*) (readPlink.cpp:148)
==2536== by 0x400CDA: main (readPlink.cpp:233)
So why is this? And is this a viable way of doing a matrix of chars?
FAM001 1 0 0 1 2 A A G G A C
FAM001 2 0 0 1 2 A A A G 0 0
Why on earth would I try to be funny about that?? That would be quite sick...
(But ok I have changed this, I had not really noticed this unfortunate coincidence)
So, I am guessing you have many lines of this type of coding.
I think your matrix idea is perhaps flawed/too complicated and a vector or array of structs would be better. This means the struct would be made up of string, int, int, ... char, char corresponding to each element in each row. Maybe string followed by chars depending on what you plan to do with the data.
The whole array of lines is just a single dimensioned array/vector. The profusion of pointers doesn't seem necessary. Columns are just a formatting artefact, nothing special as far as data structure is concerned.
A matrix using vectors is simply a vector of vectors. Suggest you google it because it is stock Stroustrup stuff. Same principle as a 2d matrix of chars which is where you us double pointers but you're asking for problems.
You can store the Pfile objects as they are read in as elements in a vector of Pfile objects and within each object is a vector of genotype as described above. All very simple, manageable, extendible and direct.
The way of the pointers is the way I was taught C++, it sure makes the program run faster right?
Probably not faster, but is is definitely much more error prone.
And could you point to an example of how to create a matrix structure with std::vector?
kemort already explained how to go about this, you would have a vector of your structure to hold each record (line). This structure has a vector to hold the genotypes.
By the way the structure I provided is probably incorrect, the sex and phenotype probably should be strings.
So then why would you suggest the second "working" snippet? IMO ptr[x*xDim + y] is much harder to read as is much more error prone than ptr[x][y].
Also your "working" snippet is also incorrect. You are trying to delete a pointer which was not allocated with new.
Watch out for those C style casts, if you must use a cast in a C++ program you should be using the proper C++ style cast (ie: static_cast<char>()) to maintain type safety. Those C style casts are not necessarily type safe. Also be careful with char cast, you could easily overflow the bounds of the type, which could lead to Undefined Behavior.
You really need to come into this century and find and download a more modern compiler. Any compiler that accepts <iostream.h> should be abandoned. And stop using malloc() in C++ programs, except in very very rare circumstances.
Ok I guess I will construct a vector of vectors, for my char matrix. So thanks for the help! :)
And also thanks a lot for the swifts responses, most appreciated.
But one final question, that I am a bit befuddled with still, should it be possible to construct a char matrix the way I devised? And if so is the function I constructed proper?
Why are you using fprintf()? You seem to be writing a C++ program so you really should be using the C++ streams instead of the more error prone C-stdio functions.
So is this because the char has no null termination character ('\0')? And the fprintf then goes out of bonds when trying to print a char as a string?
Yes, and remember using the incorrect specifier for the type invokes Undefined Behavior. If you were using C++ streams you wouldn't be having this kind of issue because the C++ streams know the variable type unlike the error prone C-stdio functions.