The function has to return the contents of the file, which is stored (in your case) in fcontents.
string Text::contents()
{
return fcontent;
}
The default constructor doesn't have to do anything in this case.
Text::Text(){}
EDIT:
Seeing how many comments there are below with new problems, I'm going to recap and answer the rest of the questions here.
in Text.h you have:
#ifndef TEXT_HH
#define TEXT_HH
#include <string> //[1]
class Text {
std::string fcontent;//[2]
public:
Text();
Text(std::string fname);
~Text();
std::string contents();
};
#endif
and Text.cpp has
// Text.cpp
#include "Text.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
Text::Text() {}
Text::Text(string fname) {
fstream f;
f.open(fname.c_str(), ios::in);//[3]
//[4]
std::stringstream stream;
while(true)
{
char buffer[1000];
f.getline(buffer, 1000);
if(f.good())
{
//This actually adds an extra newline at the end
stream << buffer << '\n';
}
else
{
break;
}
}
fcontent = stream.str();
//remove extra newline
fcontent.erase(fcontent.begin() + fcontent.size() - 1);
f.close();//This is technically unnecessary, but not bad either
}
string Text::contents() {
return fcontent;
}
Text::~Text() {}//[5]
Point 1: The header file <string>
contains the class definition for std::string, the C++ string. This should not be confused with <cstring>
which contains functions for manipulating C strings (const char *
, const char[]
, etc).
Point 2: The string class exists in the ::std namespace, which means we have to either use std::string
every time we want that class or use using namespace std;
to pull this class into the global scope. In the header file we prefer the former method because the using declaration doesn't go away, which means that the namespace will be changed for every header and source file that includes this one, which we want to avoid in general (ie. always). In the cpp file however, there is no problem using the using declaration and we do so.
Point 3: fstreams take a C string as the filename parameter, we can get the corresponding C string from a C++ string with the call c_str()
. This returns a const char *
.
Point 4: To read the whole text file into a string is less obvious than it seems because the way streams deal with eof (end-of-file) and state-checking stuff. In short it will read one more time than you want it to (I know, wanting is subjective, but is close enough I think) before setting the eof flag. That's why the state is checked after calling get and before adding what's been read to our stringstream. Streams are a fairly elaborate topic so I won't go into it in more detail here.
Point 5: Destructors on objects (non-pointers, like our fcontents is) are called automatically, so we don't need to do anything to make sure that our fcontents string is destroyed when our Text object is destroyed. When we allocate something dynamically with new
that's when we have to worry about calling delete
on it when we want to destroy it.