Professional C__ - Marc Gregoire [467]
ArticleCitations& operator=(const ArticleCitations& rhs);
string getArticle() const { return mArticle; }
size_t getNumCitations() const { return mNumCitations; }
string getCitation(size_t i) const { return mCitations[i]; }
protected:
void readFile(const string& fileName);
string mArticle;
string* mCitations;
size_t mNumCitations;
};
Code snippet from ArticleCitations\FirstAttempt\ArticleCitations.h
The implementation follows. This program is buggy! Don’t use it verbatim or as a model.
ArticleCitations::ArticleCitations(const string& fileName)
{
// All we have to do is read the file.
readFile(fileName);
}
ArticleCitations::ArticleCitations(const ArticleCitations& src)
{
// Copy the article name, author, etc.
mArticle = src.mArticle;
// Copy the number of citations.
mNumCitations = src.mNumCitations;
// Allocate an array of the correct size.
mCitations = new string[mNumCitations];
// Copy each element of the array.
for (size_t i = 0; i < mNumCitations; i++) {
mCitations[i] = src.mCitations[i];
}
}
ArticleCitations& ArticleCitations::operator=(const ArticleCitations& rhs)
{
// Check for self-assignment.
if (this == &rhs) {
return *this;
}
// Free the old memory.
delete [] mCitations;
// Copy the article name, author, etc.
mArticle = rhs.mArticle;
// Copy the number of citations.
mNumCitations = rhs.mNumCitations;
// Allocate a new array of the correct size.
mCitations = new string[mNumCitations];
// Copy each citation.
for (size_t i = 0; i < mNumCitations; i++) {
mCitations[i] = rhs.mCitations[i];
}
return *this;
}
ArticleCitations::~ArticleCitations()
{
delete [] mCitations;
}
void ArticleCitations::readFile(const string& fileName)
{
// Open the file and check for failure.
ifstream istr(fileName.c_str());
if (istr.fail()) {
throw invalid_argument("Unable to open file");
}
// Read the article author, title, etc. line.
getline(istr, mArticle);
// Skip the white space before the citations start.
istr >> ws;
size_t count = 0;
// Save the current position so we can return to it.
ios_base::streampos citationsStart = istr.tellg();
// First count the number of citations.
while (!istr.eof()) {
string temp;
getline(istr, temp);
// Skip white space before the next entry.
istr >> ws;
count++;
}
if (count != 0) {
// Allocate an array of strings to store the citations.
mCitations = new string[count];
mNumCitations = count;
// Seek back to the start of the citations.
istr.seekg(citationsStart);
// Read each citation and store it in the new array.
for (count = 0; count < mNumCitations; count++) {
string temp;
getline(istr, temp);
mCitations[count] = temp;
}
}
}
Code snippet from ArticleCitations\FirstAttempt\ArticleCitations.cpp
Testing the ArticleCitations class
Following the advice of Chapter 26, you decide to unit test your ArticleCitations class before proceeding, though for simplicity in this example, the unit test does not use a test framework. The following program asks the user for a filename, constructs an ArticleCitations class with that filename, and passes the object by value to the processCitations() function, which prints out the info using the public accessor methods on the object.
#include "ArticleCitations.h"
#include using namespace std; void processCitations(ArticleCitations cit); int main() { string fileName; while (true) { cout << "Enter a file name (\"STOP\" to stop): "; cin >> fileName; if (fileName == "STOP") { break; } // Test constructor ArticleCitations cit(fileName); processCitations(cit); } return 0; } void processCitations(ArticleCitations cit) { cout << cit.getArticle() << endl; size_t num = cit.getNumCitations(); for (size_t i = 0; i < num; i++) { cout << cit.getCitation(i) << endl; } } Code snippet from ArticleCitations\ArticleCitationsTest.cpp Message-Based Debugging You decide to test the program on the Alan Turing example (stored in a file called paper1.txt). Here is the output: Enter a file name ("STOP" to stop): paper1.txt Alan Turing."On Computable Numbers with an