file processing problem

B

B. Williams

I wrote a program that would simply output data to the screen, but now I am trying to have the data saved to a file. I don't have a problem creating the file or even outputting data to it when there is no header file to include, but I can't seem to figure out how to output the data to the file I create when the main is in a different. Will someone give me an example or show me what I am doing wrong?



#include <iostream>

#include <string>



#include <fstream>

using std::eek:fstream;



using std::cout;



class PPG{

public:

PPG(char *a, char b, int c)

{ dresscolor =b;

power = c;

setname(a);}//end constructor 1



PPG()

{ setname("Ms. Bellum");

dresscolor ='p';

power = 0;

}//end default constructor



char * getname()const {return name;}



void setname(char *a){

int l =strlen(a);

name = new char[l+1];

strcpy(name,a);

name[l] = '\0';

}//end setname



int getpower() const{return power;}

void setpower(int z){power = z;}

char getdresscolor() const{return dresscolor;}

void setdresscolor(char v){dresscolor=v;}



void print() const

{ cout << name << " likes to wear ";

switch (dresscolor){

case 'g': case 'G':

cout <<"green dresses. She uses her "; break;

case 'b':case 'B':

cout <<"blue dresses. She uses her ";break;

case 'p': case 'P':

cout <<"pink dresses. She uses her ";

}//end switch

if (power == 1)

cout << "ice breath to defeat her enemies.\n";

else if (power ==2)

cout << "ability to talk to squirrels to confuse evil villians.\n";

else if (power ==3)

cout <<"bad attitude to stop evil doers.\n";

else

cout <<"girl power to rule the world.\n";

}//end print



bool operator==(PPG &ppg)

{ return (strcmp(name, ppg.name)==0); }



private:

char * name;

char dresscolor; //g-reen, b-lue, p-pink

int power; //1-ice breath, 2- squirrel speak, 3-bad attitude

}; //end class



#include "ppg.h"

#include <iostream>

#include <fstream>

using std::eek:fstream;





int main()

{



ofstream PPG("girls.txt", ios::eek:ut);

PPG girl1("Bubbles", 'b', 2);

girl1.print();

PPG badgirl("Princess",'g', 4);

badgirl.print();





return 0;

}//end main
 
G

Gianni Mariani

B. Williams said:
I wrote a program that would simply output data to the screen, but now I
am trying to have the data saved to a file. I don't have a problem
creating the file or even outputting data to it when there is no header
file to include, but I can't seem to figure out how to output the data
to the file I create when the main is in a different. Will someone give
me an example or show me what I am doing wrong?

You need to pass a reference to the file you want to print to.

If you're using a std::eek:stream, then have your print function take a
"std::eek:stream &" (reference) as a parameter. You can have it as a
parameter to the class constructor.


Here is an example:

void PrintToThisFile( std::eek:stream & ofile )
{
ofile << "Hello world of other file\n";
}

int main()
{
PrintThisToFile( std::cout );
std::eek:fstream otherfile( "junk" );
PrintThisToFile( otherfile );
}
// caution - this is a brain dump - expect errors

...
 
A

Adrian

B. Williams said:
I wrote a program that would simply output data to the screen, but now I
am trying to have the data saved to a
file. I don't have a problem creating the file or even outputting data to
it when there is no header file to include, but I can't seem to figure out
how to output
the data to the file I create when the main is in a different. Will
someone give me an example or show me what I am doing wrong?
[code snip]

I have improved on your program. Hopefully with no mistakes. I made a few
changes.

1. To use enumerated types for the colour and power as this makes the
program more readable, improves type checking
2. Using std::string to remove all the problems with char *'s This allows
easy copying of the class with default constructor, and not having to worry
about bounds checking etc
3. Add a friend function to output your class
4. Moved the print function to private (as people done need it now)
5. Split code into 3 seperate files
6. Stopped multiple includes of header file

(Depending on platform a couple of example compile lines)
g++ -Wall -pedantic -ansi -o ppg ppg.cpp main.cpp
bcc32 -o ppg main.cpp ppg.cpp

Code to follow:-
// File
ppg.h -------------------------------------------------------------------------
#ifndef PPG_H //stop multiple includes of header
#define PPG_H

#include <ostream>
#include <string>

class PPG; //Forward definition class for friend function prototype
std::eek:stream &operator<<(std::eek:stream &os, const PPG &ppg);
//Friend prototype (not sure if you need the two about or if I am being
pedantic

//removed inline functions for clarity and moved to ppg.cpp
class PPG
{
public:
typedef enum {NoColor_e, Green_e, Blue_e, Pink_e} Color_t;
typedef enum {NoPower_e, Ice_Breath_e, Squirrel_Speak_e, Bad_Attitude_e}
Power_t;

PPG(const std::string &a, Color_t b, Power_t c);
PPG();
// Using std::string stops the need for a copy constructor now as all
types can be copied
// using the default copy constructor - no worries about memory freeing
etc

const std::string &getname() const;
void setname(const std::string &a);
Power_t getpower() const;
void setpower(Power_t z);
Color_t getdresscolor() const;
void setdresscolor(Color_t v);
bool operator==(const PPG &ppg);

//definition of friend function to output class to a stream
friend std::eek:stream &operator<<(std::eek:stream &os, const PPG &ppg);

private:
std::eek:stream &print(std::eek:stream &os) const;
std::string name;
Color_t dresscolor; // No need for descriptions now //g-reen, b-lue,
p-pink
Power_t power; // No need for descriptions now //1-ice breath, 2-
squirrel speak, 3-bad attitude
}; //end class


#endif
// End file
ppg.h -------------------------------------------------------------------------


//File
ppg.cpp -------------------------------------------------------------------------
#include <ostream>
#include "ppg.h"

//Changed to use std::string so no worries about length etc
PPG::pPG(const std::string &a, Color_t b, Power_t c)
:name(a), dresscolor(b), power(c) // Here using constructor initizalizer
lists
{
}//end constructor 1

PPG::pPG()
:name("Ms. Bellum"), dresscolor(Pink_e), power(NoPower_e) // same here
{
}//end default constructor

//changed to use std::string
const std::string &PPG::getname() const
{
return name;
}

//changed to use std::string
void PPG::setname(const std::string &a)
{
name=a;
}//end setname

PPG::power_t PPG::getpower() const
{
return power;
}

void PPG::setpower(Power_t z)
{
power = z;
}

PPG::Color_t PPG::getdresscolor() const
{
return dresscolor;
}

void PPG::setdresscolor(Color_t v)
{
dresscolor=v;
}

//changed to a private function and now uses ostream to output
std::eek:stream &PPG::print(std::eek:stream &os) const
{
os << name << " likes to wear ";
switch(dresscolor)
{
case Green_e:
os <<"green dresses. She uses her ";
break;

case Blue_e:
os <<"blue dresses. She uses her ";
break;

case Pink_e:
os <<"pink dresses. She uses her ";
break;

default:
// Always worth having this even if it does nothing. Can stop some nasty
crashes
os << "[OOPS not a known colour]";
break;
}//end switch

//changed to switch statement for style consitency
switch(power)
{
case Ice_Breath_e:
os << "ice breath to defeat her enemies.\n";
break;

case Squirrel_Speak_e:
os << "ability to talk to squirrels to confuse evil villians.\n";
break;

case Bad_Attitude_e:
os <<"bad attitude to stop evil doers.\n";
break;

default:
os <<"girl power to rule the world.\n";
}
return os;
}//end print

//changed to use std::string comparison
bool PPG::eek:perator==(const PPG &ppg)
{
return name==ppg.name;
}


std::eek:stream &operator<<(std::eek:stream &os, const PPG &ppg)
{
return ppg.print(os);
}
// end file
ppg.cpp -------------------------------------------------------------------------

// File
main.cpp -------------------------------------------------------------------------

#include "ppg.h"
#include <iostream>
#include <fstream>

using std::eek:fstream;
using std::cout;


//now uses friend function and print() to out to either cout or a file
stream
int main()
{
ofstream text_file("girls.txt");

//Now use enumerated types
PPG girl1("Bubbles", PPG::pink_e, PPG::Squirrel_Speak_e);

//PPG girl2("Bubbles2", PPG::Squirrel_Speak_e, PPG::pink_e);
//This now uses c++ type checking and will not compile where as
//PPG girl3("Bubbles3", 2, 'g'); could compile without errors
//Plus the added bonus of not having to go back and find out what 2 means

//Now we can easily output using either a file or the screen
cout << girl1;
text_file << girl1;

PPG badgirl("Princess",PPG::Green_e, PPG::NoPower_e);

cout << badgirl;
text_file << badgirl;

return 0;

}//end main

// End file
main.cpp -------------------------------------------------------------------------
 
B

B. Williams

Gianni Mariani said:
You need to pass a reference to the file you want to print to.

If you're using a std::eek:stream, then have your print function take a
"std::eek:stream &" (reference) as a parameter. You can have it as a
parameter to the class constructor.


Here is an example:

void PrintToThisFile( std::eek:stream & ofile )
{
ofile << "Hello world of other file\n";
}

int main()
{
PrintThisToFile( std::cout );
std::eek:fstream otherfile( "junk" );
PrintThisToFile( otherfile );
}
// caution - this is a brain dump - expect errors

..
This is exactly what I was looking for. I'll try to adapt my code to it.
 
B

B. Williams

B. Williams said:
This is exactly what I was looking for. I'll try to adapt my code to it.
I just wanted to thank everyone for their assistance. This is my code and
it works.

#include <iostream>

using std::cerr;

using std::endl;

using std::ios;

using std::cout;

#include <fstream>

using std::eek:fstream;



#include <cstdlib>

using std::exit;



class PPG{

public:

PPG(char *a, char b, int c)

{ dresscolor =b;

power = c;

setname(a);}//end constructor 1



PPG()

{ setname("Ms. Bellum");

dresscolor ='p';

power = 0;

}//end default constructor



char * getname()const {return name;}



void setname(char *a){

int l =strlen(a);

name = new char[l+1];

strcpy(name,a);

name[l] = '\0';

}//end setname





int getpower() const{return power;}

void setpower(int z){power = z;}

char getdresscolor() const{return dresscolor;}

void setdresscolor(char v){dresscolor=v;}



void print(std::eek:stream & outPPGFile) const

{ outPPGFile << name << " likes to wear ";

switch (dresscolor){

case 'g': case 'G':

outPPGFile <<"green dresses. She uses her "; break;

case 'b':case 'B':

outPPGFile <<"blue dresses. She uses her ";break;

case 'p': case 'P':

outPPGFile <<"pink dresses. She uses her ";

}//end switch

if (power == 1)

outPPGFile << "ice breath to defeat her enemies.\n";

else if (power ==2)

outPPGFile << "ability to talk to squirrels to confuse evil
villians.\n";

else if (power ==3)

outPPGFile <<"bad attitude to stop evil doers.\n";

else

outPPGFile <<"girl power to rule the world.\n";

}//end print



bool operator==(PPG &ppg)

{ return (strcmp(name, ppg.name)==0); }



private:

char * name;

char dresscolor; //g-reen, b-lue, p-pink

int power; //1-ice breath, 2- squirrel speak, 3-bad attitude

}; //end class



int main()

{



ofstream outPPGFile("girls.txt");



if ( !outPPGFile )

{

cerr << "File could not be opened" << endl;

exit( 1 );

} // end if





PPG girl;

girl.print(outPPGFile);

PPG girl1("Bubbles", 'b', 2);

girl1.print(outPPGFile);

PPG badgirl("Princess",'g', 4);

badgirl.print(outPPGFile);



return 0;



}//end main
 
B

B. Williams

Adrian said:
I wrote a program that would simply output data to the screen, but now I
am trying to have the data saved to a
file. I don't have a problem creating the file or even outputting data to
it when there is no header file to include, but I can't seem to figure
out how to output
the data to the file I create when the main is in a different. Will
someone give me an example or show me what I am doing wrong?
[code snip]

I have improved on your program. Hopefully with no mistakes. I made a few
changes.

1. To use enumerated types for the colour and power as this makes the
program more readable, improves type checking
2. Using std::string to remove all the problems with char *'s This allows
easy copying of the class with default constructor, and not having to
worry about bounds checking etc
3. Add a friend function to output your class
4. Moved the print function to private (as people done need it now)
5. Split code into 3 seperate files
6. Stopped multiple includes of header file

(Depending on platform a couple of example compile lines)
g++ -Wall -pedantic -ansi -o ppg ppg.cpp main.cpp
bcc32 -o ppg main.cpp ppg.cpp

Code to follow:-
// File
ppg.h -------------------------------------------------------------------------
#ifndef PPG_H //stop multiple includes of header
#define PPG_H

#include <ostream>
#include <string>

class PPG; //Forward definition class for friend function prototype
std::eek:stream &operator<<(std::eek:stream &os, const PPG &ppg);
//Friend prototype (not sure if you need the two about or if I am being
pedantic

//removed inline functions for clarity and moved to ppg.cpp
class PPG
{
public:
typedef enum {NoColor_e, Green_e, Blue_e, Pink_e} Color_t;
typedef enum {NoPower_e, Ice_Breath_e, Squirrel_Speak_e, Bad_Attitude_e}
Power_t;

PPG(const std::string &a, Color_t b, Power_t c);
PPG();
// Using std::string stops the need for a copy constructor now as all
types can be copied
// using the default copy constructor - no worries about memory freeing
etc

const std::string &getname() const;
void setname(const std::string &a);
Power_t getpower() const;
void setpower(Power_t z);
Color_t getdresscolor() const;
void setdresscolor(Color_t v);
bool operator==(const PPG &ppg);

//definition of friend function to output class to a stream
friend std::eek:stream &operator<<(std::eek:stream &os, const PPG &ppg);

private:
std::eek:stream &print(std::eek:stream &os) const;
std::string name;
Color_t dresscolor; // No need for descriptions now //g-reen, b-lue,
p-pink
Power_t power; // No need for descriptions now //1-ice breath, 2-
squirrel speak, 3-bad attitude
}; //end class


#endif
// End file
ppg.h -------------------------------------------------------------------------


//File
ppg.cpp -------------------------------------------------------------------------
#include <ostream>
#include "ppg.h"

//Changed to use std::string so no worries about length etc
PPG::pPG(const std::string &a, Color_t b, Power_t c)
:name(a), dresscolor(b), power(c) // Here using constructor initizalizer
lists
{
}//end constructor 1

PPG::pPG()
:name("Ms. Bellum"), dresscolor(Pink_e), power(NoPower_e) // same here
{
}//end default constructor

//changed to use std::string
const std::string &PPG::getname() const
{
return name;
}

//changed to use std::string
void PPG::setname(const std::string &a)
{
name=a;
}//end setname

PPG::power_t PPG::getpower() const
{
return power;
}

void PPG::setpower(Power_t z)
{
power = z;
}

PPG::Color_t PPG::getdresscolor() const
{
return dresscolor;
}

void PPG::setdresscolor(Color_t v)
{
dresscolor=v;
}

//changed to a private function and now uses ostream to output
std::eek:stream &PPG::print(std::eek:stream &os) const
{
os << name << " likes to wear ";
switch(dresscolor)
{
case Green_e:
os <<"green dresses. She uses her ";
break;

case Blue_e:
os <<"blue dresses. She uses her ";
break;

case Pink_e:
os <<"pink dresses. She uses her ";
break;

default:
// Always worth having this even if it does nothing. Can stop some nasty
crashes
os << "[OOPS not a known colour]";
break;
}//end switch

//changed to switch statement for style consitency
switch(power)
{
case Ice_Breath_e:
os << "ice breath to defeat her enemies.\n";
break;

case Squirrel_Speak_e:
os << "ability to talk to squirrels to confuse evil villians.\n";
break;

case Bad_Attitude_e:
os <<"bad attitude to stop evil doers.\n";
break;

default:
os <<"girl power to rule the world.\n";
}
return os;
}//end print

//changed to use std::string comparison
bool PPG::eek:perator==(const PPG &ppg)
{
return name==ppg.name;
}


std::eek:stream &operator<<(std::eek:stream &os, const PPG &ppg)
{
return ppg.print(os);
}
// end file
ppg.cpp -------------------------------------------------------------------------

// File
main.cpp -------------------------------------------------------------------------

#include "ppg.h"
#include <iostream>
#include <fstream>

using std::eek:fstream;
using std::cout;


//now uses friend function and print() to out to either cout or a file
stream
int main()
{
ofstream text_file("girls.txt");

//Now use enumerated types
PPG girl1("Bubbles", PPG::pink_e, PPG::Squirrel_Speak_e);

//PPG girl2("Bubbles2", PPG::Squirrel_Speak_e, PPG::pink_e);
//This now uses c++ type checking and will not compile where as
//PPG girl3("Bubbles3", 2, 'g'); could compile without errors
//Plus the added bonus of not having to go back and find out what 2 means

//Now we can easily output using either a file or the screen
cout << girl1;
text_file << girl1;

PPG badgirl("Princess",PPG::Green_e, PPG::NoPower_e);

cout << badgirl;
text_file << badgirl;

return 0;

}//end main

// End file
main.cpp -------------------------------------------------------------------------
I really like your programming, but it is a bit over my head.
 
D

Daniel T.

B. Williams said:
I wrote a program that would simply output data to the screen, but now I am
trying to have the data saved to a file. I don't have a problem creating the
file or even outputting data to it when there is no header file to include,
but I can't seem to figure out how to output the data to the file I create
when the main is in a different. Will someone give me an example or show me
what I am doing wrong?

There are several problems with the code you posted. But to answer your
explicit question, you do it the same way. Keep in mind, the
pre-processor simply pastes the header file into the cpp file at the
location of the #include statement. Now to the code review:
#include <iostream>
#include <string>
#include <fstream>

using std::eek:fstream;
using std::cout;

Don't put 'using' statements in header files.
class PPG
{

public:
PPG(char *a, char b, int c)
{
dresscolor = b;
power = c;
setname(a);
}//end constructor 1

PPG()
{
setname("Ms. Bellum");
dresscolor ='p';
power = 0;
}//end default constructor

Learn about initializer lists and the use of the 'const' keyword. Use
meaningful variable names as parameters.
char* getname()const
{
return name;
}

void setname(char *a)
{
int l =strlen(a);
name = new char[l+1];
strcpy(name,a);
name[l] = '\0';
}//end setname

Note, if the object already has a name, calling setname will leak
memory. If an object is copied, then two objects will point to the same
name object. Memory will also leak when an object is destroyed.
int getpower() const
{
return power;
}

void setpower(int z)
{
power = z;
}

char getdresscolor() const
{
return dresscolor;
}

void setdresscolor(char v)
{
dresscolor=v;
}

Only certain values are meaningful for the dress color, but you don't
check to make sure the value entered will work.
void print() const
{
cout << name << " likes to wear ";

Your 'print()' function can't send its data to a file, it will only
print to cout.
switch (dresscolor) {
case 'g':
case 'G':
cout <<"green dresses. She uses her ";
break;
case 'b':
case 'B':
cout <<"blue dresses. She uses her ";
break;
case 'p':
case 'P':
cout <<"pink dresses. She uses her ";
}//end switch

Whenever every branch in a switch/case statement has the same thing, you
should factor out the likenesses. Remember "DRY", Don't Repeat Yourself.
if (power == 1)
cout << "ice breath to defeat her enemies.\n";
else if (power == 2)
cout << "ability to talk to squirrels to confuse evil villians.\n";
else if (power == 3)
cout <<"bad attitude to stop evil doers.\n";
else
cout <<"girl power to rule the world.\n";
}//end print

bool operator==(PPG &ppg)
{
return (strcmp(name, ppg.name)==0);
}

If two different PPGs happen to have the same name, should operator==
still return true?
private:
char* name;
char dresscolor; //g-reen, b-lue, p-pink
int power; //1-ice breath, 2- squirrel speak, 3-bad attitude
}; //end class

#include "ppg.h"
#include <iostream>
#include <fstream>

using std::eek:fstream;

int main()
{
ofstream PPG("girls.txt", ios::eek:ut);

Don't give an object the same name as a class, this will hide the class.
 
D

Daniel T.

Adrian said:
Code to follow:-

Good job Adrian, just a few notes to what you did.
// File
ppg.h
-------------------------------------------------------------------------
#ifndef PPG_H //stop multiple includes of header
#define PPG_H

#include <ostream>

That's supposed to be:
#include <iostream>
or
#include said:
#include <string>

class PPG; //Forward definition class for friend function prototype
std::eek:stream &operator<<(std::eek:stream &os, const PPG &ppg);
//Friend prototype (not sure if you need the two about or if I am being
pedantic

No need to forward declare the class, nor is there need to declare the
function here.
//removed inline functions for clarity and moved to ppg.cpp
class PPG
{
public:
typedef enum {NoColor_e, Green_e, Blue_e, Pink_e} Color_t;
typedef enum {NoPower_e, Ice_Breath_e, Squirrel_Speak_e, Bad_Attitude_e}
Power_t;

No need for a typedef. Just, for example:

enum Color_t { noColor, green, blue, pink };
PPG(const std::string &a, Color_t b, Power_t c);
PPG();
// Using std::string stops the need for a copy constructor now as all
types can be copied
// using the default copy constructor - no worries about memory freeing
etc

const std::string &getname() const;
void setname(const std::string &a);
Power_t getpower() const;
void setpower(Power_t z);
Color_t getdresscolor() const;
void setdresscolor(Color_t v);
bool operator==(const PPG &ppg);

//definition of friend function to output class to a stream
friend std::eek:stream &operator<<(std::eek:stream &os, const PPG &ppg);

private:
std::eek:stream &print(std::eek:stream &os) const;
std::string name;
Color_t dresscolor; // No need for descriptions now //g-reen, b-lue,
p-pink
Power_t power; // No need for descriptions now //1-ice breath, 2-
squirrel speak, 3-bad attitude
}; //end class


#endif
// End file
ppg.h
-------------------------------------------------------------------------


//File
ppg.cpp

It's generally better to put the class' include first.
//Changed to use std::string so no worries about length etc
PPG::pPG(const std::string &a, Color_t b, Power_t c)
:name(a), dresscolor(b), power(c) // Here using constructor initizalizer
lists
{
}//end constructor 1

PPG::pPG()
:name("Ms. Bellum"), dresscolor(Pink_e), power(NoPower_e) // same here
{
}//end default constructor

//changed to use std::string
const std::string &PPG::getname() const
{
return name;
}

//changed to use std::string
void PPG::setname(const std::string &a)
{
name=a;
}//end setname

PPG::power_t PPG::getpower() const
{
return power;
}

void PPG::setpower(Power_t z)
{
power = z;
}

PPG::Color_t PPG::getdresscolor() const
{
return dresscolor;
}

void PPG::setdresscolor(Color_t v)
{
dresscolor=v;
}

//changed to a private function and now uses ostream to output
std::eek:stream &PPG::print(std::eek:stream &os) const
{
os << name << " likes to wear ";
switch(dresscolor)
{
case Green_e:
os <<"green dresses. She uses her ";
break;

case Blue_e:
os <<"blue dresses. She uses her ";
break;

case Pink_e:
os <<"pink dresses. She uses her ";
break;

default:
// Always worth having this even if it does nothing. Can stop some nasty
crashes
os << "[OOPS not a known colour]";
break;
}//end switch

It would probably be better to make it so the class can't possibly have
an unknown dress color. That would mean changing the
"setdresscolor(Color_t)" function.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top