using namespace std
in the header file, very bad. If you've been looking around our site for a few months you should see this suggestion come up quite often, if not, then read up on the discussion read up on the discussion and learn about it.Again something that comes up a lot, a global identifier starting with underscore. In this case it is aggravated for being a macro and with a common name used by libraries:
Read up about the reserved C++ identifiers Read up about the reserved C++ identifiers. As a side recommendation, use ALL_UPPERCASE
for #defines
to differentiate them from actual C++ entities (the preprocessor is a mini-language inside C++).
using namespace std
in the header file, very bad. If you've been looking around our site for a few months you should see this suggestion come up quite often, if not, then read up on the discussion and learn about it.Again something that comes up a lot, a global identifier starting with underscore. In this case it is aggravated for being a macro and with a common name used by libraries:
Read up about the reserved C++ identifiers. As a side recommendation, use ALL_UPPERCASE
for #defines
to differentiate them from actual C++ entities (the preprocessor is a mini-language inside C++).
using namespace std
in the header file, very bad. If you've been looking around our site for a few months you should see this suggestion come up quite often, if not, then read up on the discussion and learn about it.Again something that comes up a lot, a global identifier starting with underscore. In this case it is aggravated for being a macro and with a common name used by libraries:
Read up about the reserved C++ identifiers. As a side recommendation, use ALL_UPPERCASE
for #defines
to differentiate them from actual C++ entities (the preprocessor is a mini-language inside C++).
- This was already mentioned in a OP comment:
Parser
is a bad name for a class that simply splits a source file into lines. Parsing is the process of "analysing a string of symbols, either in natural language or in computer languages, conforming to the rules of a formal grammar". In simpler terms, parsing means making sense of a set of symbols and/or text. Your class itis pretty far from that. Perhaps something likeTextFileReader
would be a more honest name.
From a first glance, it looks strange that your class has so many operators for arithmetic and comparison. Since each "Parser" is just a container to the lines of a file, does it make sense to be able to add/subtract instances? Doesn't make much to me. Same for the comparisons. I can relate to comparing files for equality, but for
<
,><= | >=
ordering has never occurred to me. Not by contents, at least.Why do you use a
char*
for thefilename
is beyond my understanding, specially when the method that clones it already takes its input as astd::string
. Storing it as a C++ string would be just so much simpler.exit
ing a C++ program is about as crude as it gets when it comes to error handling. Please just throw an exception:void panic(const std::string & msg) { throw std::runtime_error("Error: " + msg + "\n"); }
The ideal would also be defining a custom exception type derived from std::runtime_error
, if you want to refine it further.
Why do you have a
protected
section in your class? No signs of inheritance around, so all the internal details should beprivate
.getFilename()
andgetContent()
should also beconst
since they don't (and shouldn't) mutate member data.A
std::list
is probably going to have inferior performance if compared to astd::vector
in this case due to poor data locality. With a list, each line is going to be allocated as a separate memory block (think about list nodes). Of course that without measuring it is impossible to say if this is a performance problem to your application, but at any rate, I would always start with avector
and thenonly upgrade to other structures only if really neededthere is a compelling reason.
- This was already mentioned in a OP comment:
Parser
is a bad name for a class that simply splits a source file into lines. Parsing is the process of "analysing a string of symbols, either in natural language or in computer languages, conforming to the rules of a formal grammar". In simpler terms, parsing means making sense of a set of symbols and/or text. Your class it pretty far from that.
From a first glance, it looks strange that your class has so many operators for arithmetic and comparison. Since each "Parser" is just a container to the lines of a file, does it make sense to be able to add/subtract instances? Doesn't make much to me. Same for the comparisons. I can relate to comparing files for equality, but for
<
,>
ordering has never occurred to me. Not by contents, at least.Why do you use a
char*
for thefilename
is beyond my understanding, specially when the method that clones it already takes its input as astd::string
.exit
ing a C++ program is about as crude as it gets when it comes to error handling. Please just throw an exception:void panic(const std::string & msg) { throw std::runtime_error("Error: " + msg + "\n"); }
The ideal would also be defining a custom exception type derived from std::runtime_error
.
Why do you have a
protected
section in your class? No signs of inheritance around, so all the internal details should beprivate
.getFilename()
andgetContent()
should also beconst
since they don't (and shouldn't) mutate member data.A
std::list
is probably going to have inferior performance if compared to astd::vector
in this case due to poor data locality. With a list, each line is going to be allocated as a separate memory block (think about list nodes). Of course that without measuring it is impossible to say if this is a performance problem to your application, but at any rate, I would always start with avector
and then upgrade to other structures only if really needed.
- This was already mentioned in a OP comment:
Parser
is a bad name for a class that simply splits a source file into lines. Parsing is the process of "analysing a string of symbols, either in natural language or in computer languages, conforming to the rules of a formal grammar". In simpler terms, parsing means making sense of a set of symbols and/or text. Your class is pretty far from that. Perhaps something likeTextFileReader
would be a more honest name.
From a first glance, it looks strange that your class has so many operators for arithmetic and comparison. Since each "Parser" is just a container to the lines of a file, does it make sense to be able to add/subtract instances? Doesn't make much to me. Same for the comparisons. I can relate to comparing files for equality, but for
<= | >=
ordering has never occurred to me. Not by contents, at least.Why do you use a
char*
for thefilename
is beyond my understanding, specially when the method that clones it already takes its input as astd::string
. Storing it as a C++ string would be just so much simpler.exit
ing a C++ program is about as crude as it gets when it comes to error handling. Please just throw an exception:void panic(const std::string & msg) { throw std::runtime_error("Error: " + msg + "\n"); }
The ideal would also be defining a custom exception type derived from std::runtime_error
, if you want to refine it further.
Why do you have a
protected
section in your class? No signs of inheritance around, so all the internal details should beprivate
.getFilename()
andgetContent()
should also beconst
since they don't (and shouldn't) mutate member data.A
std::list
is probably going to have inferior performance if compared to astd::vector
in this case due to poor data locality. With a list, each line is going to be allocated as a separate memory block (think about list nodes). Of course that without measuring it is impossible to say if this is a performance problem to your application, but at any rate, I would always start with avector
and only upgrade to other structures if there is a compelling reason.
From a first glance, it looks strange that your class has so many operators for arithmetic and comparison. Since each "Parser" is just a container to the lines of a file, does it make sense to be able to add/subtract instances? Doesn't make much to me. Same for the comparisons. I can relate to comparing files for equality, but for
<
,>
ordering has never occurred to me. Not by contents, at least.Why do you use a
char*
for thefilename
is beyond my understanding, specially when the method that clones it already takes its input as astd::string
.exit
ing a C++ program is about as crude as it gets when it comes to error handling. Please just throw an exception:void panic(const std::string & msg) { throw std::runtime_error("Error: " + msg + "\n"); }
Why do you have a
protected
section in your class? No signs of inheritance around, so all the internal details should beprivate
.getFilename()
andgetContent()
should also beconst
since they don't (and shouldn't) mutate member data.A
std::list
is probably going to have inferior performance if compared to astd::vector
in this case due to poor data locality. With a list, each line is going to be allocated as a separate memory block (think about list nodes). Of course that without measuring it is impossible to say if this is a performance problem to your application, but at any rate, I would always start with avector
and then upgrade to other structures only if really needed.
From a first glance, it looks strange that your class has so many operators for arithmetic and comparison. Since each "Parser" is just a container to the lines of a file, does it make sense to be able to add/subtract instances? Doesn't make much to me. Same for the comparisons. I can relate to comparing files for equality, but for
<
,>
ordering has never occurred to me. Not by contents, at least.Why do you use a
char*
for thefilename
is beyond my understanding, specially when the method that clones it already takes its input as astd::string
.exit
ing a C++ program is as crude as it gets when it comes to error handling. Please just throw an exception:void panic(const std::string & msg) { throw std::runtime_error("Error: " + msg + "\n"); }
Why do you have a
protected
section in your class? No signs of inheritance around, so all the internal details should beprivate
.getFilename
andgetContent
should also beconst
since they don't (and shouldn't) mutate member data.
From a first glance, it looks strange that your class has so many operators for arithmetic and comparison. Since each "Parser" is just a container to the lines of a file, does it make sense to be able to add/subtract instances? Doesn't make much to me. Same for the comparisons. I can relate to comparing files for equality, but for
<
,>
ordering has never occurred to me. Not by contents, at least.Why do you use a
char*
for thefilename
is beyond my understanding, specially when the method that clones it already takes its input as astd::string
.exit
ing a C++ program is about as crude as it gets when it comes to error handling. Please just throw an exception:void panic(const std::string & msg) { throw std::runtime_error("Error: " + msg + "\n"); }
Why do you have a
protected
section in your class? No signs of inheritance around, so all the internal details should beprivate
.getFilename()
andgetContent()
should also beconst
since they don't (and shouldn't) mutate member data.A
std::list
is probably going to have inferior performance if compared to astd::vector
in this case due to poor data locality. With a list, each line is going to be allocated as a separate memory block (think about list nodes). Of course that without measuring it is impossible to say if this is a performance problem to your application, but at any rate, I would always start with avector
and then upgrade to other structures only if really needed.