Archived

This topic is now archived and is closed to further replies.

fstream question

This topic is 5147 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

hi, first off, this is part of an assignment i'm trying to work on; i'm not looking for the "answer", rather advice for troubleshooting or different avenues of approach. i've written a custom class for file IO, and for some reason i can't seem to be able to read an existing file. here's the abbridged code
//file.h

class File{
private:
     fstream localStream;

public:
	File(const char*, int);
	bool getData(char*, long&, double&);
	bool printInvoice(const Invoice&);
};

   
//file.cpp

File::File(const char fileName[], int mode){
   fstream localStream(fileName, mode);
   //cout << "ctor success!" << endl;

}

bool File::getData(char custName[], long &act, double &vol){
   localStream.get(custName, 15);

   //attempt read

   if(!localStream) return false;     //error or EOF


   localStream >> act >> vol;
   localStream.get();		//kill newline character

   return true;
}

bool File::PrintInvoice(const Invoice &i)
{
   long account;
   double volume;
   char name[15]; 

   i.getData(name, account, volume);

   //attempt write

   localStream << name; 
   if(!localStream) return false;	//error writing


   localStream << setw(ACCOUNT_COL_WIDTH) << account
	       << setw(DEFAULT_COL_WIDTH) << volume
	       << setw(DEFAULT_COL_WIDTH) << i << endl;
   return true;
}
i've checked the obvious: the filepath is correct, objects of type File are being instantiated, even printInvoice can create a new file in the app directory. in getData(), all parameters are used for output. i've tested this same approach by creating a local fstream object in main() with an identical method. works w/out a hitch, reads the file data just fine. i have a feeling that there's a problem with the way my File class objects are being created. this may be stupid, but i'm not sure if it's legal to define the local fstream object in the ctor. if this is the case, then the local fstream member (localStream) really doesn't have any of its properties set (what file and mode). ok, fine. i then tested by defining localStream as a reference and a pointer (to an fstream) and then creating it in the ctor. both cases didn't fly, with the compiler (VS.Net) stating that statics/constants must be declared in the ctor. meaningless, since the member is neither static nor a constant (i'm also aware of the fact that class data members cannot be assigned in the definition; only in the ctor or out outside of the class, such as in the specification file). anyway, could someone offer some advice as to what's up? many thanks in advance! ..:: mirirom ::.. [edited by - mirirom on November 9, 2003 12:49:41 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You need to learn about constructor initializer lists.
You are making a new file stream in your constructor, instead of initialising the existing one.

Share this post


Link to post
Share on other sites
too late! i saw the suggested solution . thanks ...

but actually, that was my first original approach!
localStream(fileName, mode); 


this makes total sense since stating the type to the left of the identifier is a definition and therefore would be creating an fstream object only visible to the ctor. in my mind, the above statement just "recalls" the ctor to the fstream object with new (and correct values).

but the compiler seems to tell me otherwise, stating that
localStream(fileName, mode) 

"does not evaluate to a function"...

hmmm

Share this post


Link to post
Share on other sites
well, i came up with a solution that goes against the litteral grain of the requirements statement. we were asked to create the class and it "should contain one data member of type fstream". ok, fine. this doesn''t say "contains one data member of type fstream POINTER".

perhaps the instructor is trying to give us what we get at work all day, poorly written instructions. that''s it! blame the teacher!

thanks again for your help guys. the enclosed solution works just fine.

i do have one other question though. the solution prosted previously stated that a simple
localStream(name, mode);
would do the trick. i tried this but the compiler barked back stating that said line doesn''t evaluate to a function. why not?
(i''m a C#ener by day so some of this is almost like an eye- opening history class for me). i realize that it''s ok to define local variables within a class definition, however, you can only assign them in the class'' ctor call (save for static types defined outside of the class specification).

that being the case, why does localStream(name, mode) fail? do object declarations/definitions (w/out assignments) still call their own ctors when they''re defined within a new class? if that''s the case, then the above line would seem like a second call to a ctor which (i''m assuming, unless C++ has yet another caveat under the hood) is illegal.

thanks again...


//file.h

class File{
private:
fstream* localStream;

public:
File(const char*, int);
bool getData(char*, long&, double&);
bool printInvoice(const Invoice&);
};


//file.cpp

File::File(const char fileName[], int mode)
{
locatStream = new fstream(fileName, mode);
}

bool File::getData(char custName[], long &act, double &vol)
{
localStream->get(custName, 15); //attempt read

if(!*(localStream)) return false; //error or EOF


*(localStream) >> act >> vol;
localStream->get(); //kill newline character

return true;
}

bool File::PrintInvoice(const Invoice &i)
{
long account; double volume; char name[15];
i.getData(name, account, volume);

*(localStream) << name; //attempt write

if(!*(localStream)) return false; //error writing


*(localStream) << setw(ACCOUNT_COL_WIDTH) << account
<< setw(DEFAULT_COL_WIDTH) << volume
<< setw(DEFAULT_COL_WIDTH) << i << endl;
return true;
}


Share this post


Link to post
Share on other sites
If you do like that, you must have a destructor as well. Your initial problem was that you declared a local object in the constructor that was destroyed after the object was created.

You should do like this:
class File{
public:
File(const char* fileName, int mode) : localStream(fileName, mode) {};
// or
File(const char* fileName, int mode) {
localStream.open(fileName, mode);
}

bool getData(char*, long&, double&);
bool printInvoice(const Invoice&);
private:
fstream localStream;
};

Share this post


Link to post
Share on other sites
quote:
Original post by mirirom
why was
File(const char name[], int mode)
{
localStream(name, mode);
}


being flagged as an error?
Because it doesn''t make sense. What you have there is a function call (or perhaps a creating a temporary, if localStream was a class).

A few example of construction:
type var;            // construct with default constructor
type var("xxx"); // construct with some constructor
type var = "xxx"; // construct with default constructor, then assign/copy it.
var.whatever("xxx"); // do something to already created object
type("xxx"); // a temporary variable without a name.

If you don''t have the member variable in the constructor''s initialization list (my first example), it has already been created with its default constructor when you enter the constructor''s function body.

If you unconditionally want to open the file in the constructor, you should have the constructor like this:
File(const char* fileName, int mode) : localStream(fileName, mode) {};.

If you only want to open the file in some cases, for some reason, you need to do this:
File(const char* fileName, int mode) : localStream()
{
localStream.open(fileName, mode);
}


It is always good practice to have all members in the constructor initilization list (after the argument list, colon, and the function body).

Share this post


Link to post
Share on other sites
hi C,

thanks for clarifying/reaffirming the subject! an rvalue sitting there by itself is definitely ridiculous.

one key piece of information that had yet to be broadcast to the students was the open() method of type fstream (so far we''ve only passed file names and modes explicitly into ctor calls for types f/if/ofstream objs).

thanks again...

Share this post


Link to post
Share on other sites