What is the best option if I want to "upgrade" old C-code to newer C++ when reading a file with a semicolon delimiter:
/* reading in from file C-like: */
fscanf(tFile, "%d", &mypost.nr); /*delimiter ; */
fscanf(tFile, " ;%[^;];", mypost.aftername);/* delimiter ; */
fscanf(tFile, " %[^;]", mypost.forename); /*delimiter ; */
fscanf(tFile, " ;%[^;];", mypost.dept);/*delimiter ; */
fscanf(tFile, " %[^;];", mypost.position);/* delimiter ; */
fscanf(tFile, "%d", &mypost.nr2);
//eqivalent best C++ method achieving the same thing?
You could overload the right-shift operator on istream for your struct, so:
std::istream& operator>>(std::istream& is, mypost_struct& mps) {
is >> mps.nr;
is.ignore(1, ';');
is.getline(mps.forename, 255, ';');
is.getline(mps.aftername, 255, ';');
is >> mps.dept;
is.ignore(1, ';');
is >> mps.position;
is.ignore(1, ';');
is >> mps.nr2;
return is;
}
Subsequently, input is as simple as is >> mypost;
, where is
is the file that you have opened.
Edit: @UncleBens Thanks for pointing this out, I had forgotten to take spaces in account. I have updated the answer, assuming that forename and aftername are likely to contain spaces. And there was this rather embarrasing bit about the delimiters being double-quoted...
I just checked it using a struct definition as under:
struct mypost_struct {
int nr;
char forename[255], aftername[255];
int dept, position, nr2;
};
.. and the result was as expected.
As @susmits says, but you can also use the returned stream as a conditional, like:
if (is >> mps.nr && is.ignore(1, ";") && is >> mps.aftername && ...) {
// all is well ...
} else {
// bad input format
}
or even:
if (is >> mps.nr >> ignore(";") >> mps.aftername >> ...) {
// all is well ...
} else {
// bad input format
}
What is the best option if I want to
"upgrade" old C-code to newer C++...?
IMHO, the best way to do this would be to read the file line-by-line and use regular expressions for parsing.