Help with simple file I/O :)

K

Kush

Hello All,

I am having problem writing some data to file and I do not understand
my mistake / misconception.
I am trying to write some simple text to file but the text is rather
output to screen!

Below is my entire code from my problem, but I just want to focus on
the method "write_percentage_per_side_to_file(ofstream &os)". From my
understanding I am passing an ofstream object which I declared in main(
) as "ofstream os = ("C:\\output.txt", ios::eek:ut);" into this method,
and since I declared this as an output stream object, that using:

os << "Text"

Would write this to the filename I specified in my declaration of "os".

Any help is appreciated!

Cheers,

Kush

----------------------------------------------------------------------------------------------------------------------------------------
#include <iostream.h>
#include <math.h>
#include <fstream.h>

//********************************************************Class
definitions
class coordinate
{
private:
int x, y;
public:
void initialize(int a, int b);
int provide_x_coordinate(void);
int provide_y_coordinate(void);
};

class side
{
private:
coordinate left_side, right_side;
public:
void initialize(int ax, int ay, int bx, int by);
double length(void);
};

class property
{
private:
side side1, side2, side3, side4;
double perimeter(void);
public:
void initialize(void);
void write_percentage_per_side_to_file(ofstream &os);
};

//********************************************************coordinate
void coordinate::initialize(int a, int b)
{
x = a;
y = b;
}

int coordinate::provide_x_coordinate(void)
{
return x;
}

int coordinate::provide_y_coordinate(void)
{
return y;
}

//********************************************************side
void side::initialize(int ax, int ay, int bx, int by)
{
left_side.initialize(ax, ay);
right_side.initialize(bx, by);
}

double side::length(void)
{
int left_x, left_y, right_x, right_y;

left_x = left_side.provide_x_coordinate();
left_y = left_side.provide_y_coordinate();
right_x = right_side.provide_x_coordinate();
right_y = right_side.provide_y_coordinate();

return ( sqrt( ((right_x - left_x) * (right_x - left_x)) + ((right_y -
left_y) * (right_y - left_y)) ) );
}

//********************************************************property
void property::initialize(void)
{
side1.initialize(1, 6, 10, 10);
side2.initialize(10, 10, 36, 4);
side3.initialize(36, 4, 0, 0);
side4.initialize(0, 0, 1, 6);
}

double property::perimeter(void)
{
return (side1.length() + side2.length() + side3.length() +
side4.length() );
}

void property::write_percentage_per_side_to_file(ofstream &os)
{
os << "The percentage length of side1 relative to the perimeter is "
<< (side1.length() / perimeter() ) * 100 << endl
<< "The percentage length of side2 relative to the perimeter is " <<
(side2.length() / perimeter() ) * 100 << endl
<< "The percentage length of side3 relative to the perimeter is " <<
(side3.length() / perimeter() ) * 100 << endl
<< "The percentage length of side4 relative to the perimeter is " <<
(side4.length() / perimeter() ) * 100 << endl;
os.close();
}

//********************************************************main()

void main(void)
{
property lot;
lot.initialize();
ofstream os = ("C:\\output.txt", ios::eek:ut);
lot.write_percentage_per_side_to_file(os);
}
//********************************************************end of program
 
S

Salt_Peter

Kush said:
Hello All,

I am having problem writing some data to file and I do not understand
my mistake / misconception.
I am trying to write some simple text to file but the text is rather
output to screen!

Below is my entire code from my problem, but I just want to focus on
the method "write_percentage_per_side_to_file(ofstream &os)". From my
understanding I am passing an ofstream object which I declared in main(
) as "ofstream os = ("C:\\output.txt", ios::eek:ut);" into this method,
and since I declared this as an output stream object, that using:

os << "Text"

Would write this to the filename I specified in my declaration of "os".

Any help is appreciated!

Cheers,

Kush

#include <iostream>
#include <cmath>
#include said:
//********************************************************Class
definitions
class coordinate
{
private:
int x, y;
public:
void initialize(int a, int b);
int provide_x_coordinate(void);
int provide_y_coordinate(void);
};

class coordinate
{
int x, y;
public:
coordinate(int a, int b);
int getx() const;
int gety() const;
};
class side
{
private:
coordinate left_side, right_side;
public:
void initialize(int ax, int ay, int bx, int by);
double length(void);
};

class side
{
coordinate left_side, right_side;
public:
side(int ax, int ay, int bx, int by);
side(const coordinate& ls, const coordiante& rs);
double length() const;
}
class property
{
private:
side side1, side2, side3, side4;
double perimeter(void);
public:
void initialize(void);
void write_percentage_per_side_to_file(ofstream &os);
};

//********************************************************coordinate
void coordinate::initialize(int a, int b)
{
x = a;
y = b;
}

coordinate::coordinate(int a, int b) : x(a), y(b)
{
}
int coordinate::provide_x_coordinate(void)
{
return x;
}

int coordinate::getx() const
{
return x;
}
int coordinate::provide_y_coordinate(void)
{
return y;
}

//********************************************************side
void side::initialize(int ax, int ay, int bx, int by)
{
left_side.initialize(ax, ay);
right_side.initialize(bx, by);
}

again, use ctor. Why? Because there are more ctors than meet the eye:
def ctor, parametized ctor, copy ctor and assignment operator - which
itself is not a ctor. If you don't write the default ctors and op=, the
compiler must generate them anyways. And the compiler will not default
initialize members unless you tell it to.
double side::length(void)
{
int left_x, left_y, right_x, right_y;

left_x = left_side.provide_x_coordinate();
left_y = left_side.provide_y_coordinate();
right_x = right_side.provide_x_coordinate();
right_y = right_side.provide_y_coordinate();

return ( sqrt( ((right_x - left_x) * (right_x - left_x)) + ((right_y -
left_y) * (right_y - left_y)) ) );
}

//********************************************************property
void property::initialize(void)
{
side1.initialize(1, 6, 10, 10);
side2.initialize(10, 10, 36, 4);
side3.initialize(36, 4, 0, 0);
side4.initialize(0, 0, 1, 6);
}

double property::perimeter(void)
{
return (side1.length() + side2.length() + side3.length() +
side4.length() );
}

void property::write_percentage_per_side_to_file(ofstream &os)

You should be passing the std::eek:fstream by std::eek:stream reference:
void property::write_percentage_per_side_to_file(std::eek:stream &os)
{
os << "The percentage length of side1 relative to the perimeter is "
<< (side1.length() / perimeter() ) * 100 << endl
<< "The percentage length of side2 relative to the perimeter is " <<
(side2.length() / perimeter() ) * 100 << endl
<< "The percentage length of side3 relative to the perimeter is " <<
(side3.length() / perimeter() ) * 100 << endl
<< "The percentage length of side4 relative to the perimeter is " <<
(side4.length() / perimeter() ) * 100 << endl;
os.close();
}

//********************************************************main()

void main(void)
{
property lot;
lot.initialize();
ofstream os = ("C:\\output.txt", ios::eek:ut);

Where is the error checking? How do you what, if anything, failed?

std::eek:fstream ofs;
ofs.open("C:\\output.txt");
if(!ofs || !ofs.is_open() )
{
std::cerr << "error while opening file for output.\n";
return -1;
}
 
J

James Willmott

Salt_Peter said:
coordinate::coordinate(int a, int b) : x(a), y(b)

What is this construct doing? I haven't seen a function defined like
this before.

Thanks,

jw.
 
S

Salt_Peter

James said:
What is this construct doing? I haven't seen a function defined like
this before.
Coders who consider pointers to be friends have few acquaintances.
Thanks,

jw.

Its constructing an instance of coordinate using an "init list" with a
and b as parameters to initialize the x and y members. Very fundamental
in C++ and usefull since the ctor does not need to allocate the 2
integers and *then* initialize their values. allocation +
initialization is simultaneously carried out.

Set a breakpoint in the ctors and watch the members x and y:

#include <iostream>

class coordinate
{
int x, y;
public:
// def ctor + init list
coordinate() : x(0), y(0)
{
std::cout << "coordinate()\n";
}
// parametized ctor + init list
coordinate(int a, int b) : x(a), y(b)
{
std::cout << "ctor coordinate(int,int)\n";
}
// copy ctor
coordinate(const coordinate& copy)
{
std::cout << "copy ctor coordinate\n";
x = copy.x;
y = copy.y;
}
};

int main()
{
coordinate coord; // def ctor invoked
coordinate another(99,11); // parametized ctor invoked
coordinate coord2(coord); // copy ctor invoked
coordinate coord3 = another; // also a copy since
}

/* output:
coordinate()
ctor coordinate(int,int)
copy ctor coordinate
copy ctor coordinate
*/

Can you see why this is usefull? Its absolutely impossible to create an
instance of coordinate where x and y are left un-initialized by
mistake. Say goodbye to bugs, thanks to the creator of the class.
Next: assignment operator.

By the way, other languages also have the compiler provide default
ctors, they just don't tell you about it nor give you access to them.
C++ takes a different view, ctors are one of its cornerstones.
 
K

Kai-Uwe Bux

You forgot to quote the empty body:
{
}
What is this construct doing? I haven't seen a function defined like
this before.

It's a constructor using an initializer list. Are you sure you never saw
that? It should be explained in any book on C++.


Best

Kai-Uwe Bux
 
J

James Willmott

Kai-Uwe Bux said:
James Willmott wrote:




You forgot to quote the empty body:
{
}



It's a constructor using an initializer list. Are you sure you never saw
that? It should be explained in any book on C++.

My C++ book doesn't even have namespaces in it.

I've never heard of initialiser lists, but now that I know what they're
called I can research them more myself. :)

Thanks,
jw.
 
J

James Willmott

Kai-Uwe Bux said:
James Willmott wrote:


{
}

What's the benefit of doing that versus...

coordinate::coordinate(int a, int b){
x=a;
y=b;
}

They seem to have the same end result at first glance?
It's a constructor using an initializer list. Are you sure you never saw
that? It should be explained in any book on C++.

My C++ book doesn't even have namespaces in it. :)

I've never heard of initialiser lists, but now that I know what they're
called I can research them more myself.

Thanks,
jw.
 
E

Emmanuel Deloget

James Willmott a écrit :
What's the benefit of doing that versus...

coordinate::coordinate(int a, int b){
x=a;
y=b;
}

They seem to have the same end result at first glance?

But they don't work in the same way. The version with the initializer
list constructs x and y with the corresponding values, while the second
version construct them, then assign the value. While this is not very
important for simple types, it can make a huge difference for more
complex type where both the construction and the code for operator=()
is slower. This is also the only way to construct sub objects that
doesn't have a default constructor, or to assign references. For
instance:

class C
{
int& a;
public:
C(int val)
{
a = val;
}
};

Doesn't work, because the reference requires to be initialized before
you enter in the constructor body. You have to use a initializer list
in this case.

Of course you did: if class B inherit class A, how does B call the
constructor of A?
My C++ book doesn't even have namespaces in it. :)

I really suggest you to pick another book then :)

Regards,

-- Emmanuel Deloget, Artware
 
J

James Willmott

Emmanuel said:
But they don't work in the same way. The version with the initializer
list constructs x and y with the corresponding values, while the second
version construct them, then assign the value. While this is not very
important for simple types, it can make a huge difference for more
complex type where both the construction and the code for operator=()
is slower. This is also the only way to construct sub objects that
doesn't have a default constructor, or to assign references. For
instance:

class C
{
int& a;
public:
C(int val)
{
a = val;
}
};

Doesn't work, because the reference requires to be initialized before
you enter in the constructor body. You have to use a initializer list
in this case.

class C
{
int& a;
public:
C(int val) : a(val)
{
}
};

Like this then?
Of course you did: if class B inherit class A, how does B call the
constructor of A?

Ok, yes I did, but I didn't recognise it as such.
I really suggest you to pick another book then :)

I intend to.

Thanks,

jw.
 
?

=?ISO-8859-15?Q?Bo_M=F8ller?=

James said:
What's the benefit of doing that versus...

coordinate::coordinate(int a, int b){
x=a;
y=b;
}

They seem to have the same end result at first glance?
No.
You can always initialize a member, but if the member is const, then
you can not assign a value to it once it has been initialized!

try this code:
#include <ostream>

class Problem
{
public:
Problem(int n);
private:
const int m_number;
};

Problem::problem(int n)
{
m_number = n; // Illegal because m_number is const!
}

int main()
{
Problem p1(1);
}

The point is the contructor will always initialize the members before
entering the body of the constructor. By giving an initializer list
you specify what values will be used to initialize the member. If no
initialiser list is given default-initialisation occurs.

Bo Møller
Hobbyist
 
E

Earl Purple

A few points on the code. That I have not commented on any particular
issue does not mean that the code is good at that point. It simply
means I did not comment on it.

Wrong headers. <iostream> <cmath> and <fstream> are the correct
headers. You are a new C++ programmer or one from 10 years ago? Why are
*new* C++ programmers being taught to include old headers?
//********************************************************Class
definitions
class coordinate
{
private:
int x, y;
public:
void initialize(int a, int b);

Bad as already pointed out. Do not have generally have public
initialize() methods. You might have a private one which is called by a
constructor.
int provide_x_coordinate(void);
int provide_y_coordinate(void);

Bad style. Do not use (void) for functions with no parameters but
instead use ()
class property
{
private:
side side1, side2, side3, side4;

Almost certainly not good. Better to use a fixed length array. That
also might not be the best design but it's pretty much likely to be
better than four distinct members such that you cannot iterate through
them.
double perimeter(void);
public:
void initialize(void);
void write_percentage_per_side_to_file(ofstream &os);

Bad for three reasons. Firstly this method is not going to modify the
class so it should be a const method. Secondly, it is bad to take
ofstream & instead of the generic ostream & unless it is going to use
features specific to ofstream. (And you'll need std:: to qualify
ostream). The third bad thing is that the function calculates something
and outputs it to a stream. Why can't you calculate something and
return it?
};

void property::write_percentage_per_side_to_file(ofstream &os)
{
os << "The percentage length of side1 relative to the perimeter is "
<< (side1.length() / perimeter() ) * 100 << endl
<< "The percentage length of side2 relative to the perimeter is " <<
(side2.length() / perimeter() ) * 100 << endl
<< "The percentage length of side3 relative to the perimeter is " <<
(side3.length() / perimeter() ) * 100 << endl
<< "The percentage length of side4 relative to the perimeter is " <<
(side4.length() / perimeter() ) * 100 << endl;
os.close();
}

Bad to close the stream at the end. If you had used an array you could
do something like:

for ( int i=0; i<numSides; ++i )
{
os << "The percentage length of side" << i << " relative to the
perimeter is "
<< side.length() / perimeter() ) * 100 << '\n';
}
os.flush(); // if you really want the flush

The "function that calculates something" that I mentioned earlier would
give you that percentage. Instead of putting that calculation in your
loop here, you could call it each time. It could also be a public
method so it could be called externally if someone using the class
needs this percentage.
void main(void)

main returns int. And don't use (void) of course as parameter list.
{
property lot;
lot.initialize();
ofstream os = ("C:\\output.txt", ios::eek:ut);

Remove the = sign.

If you used int main( int argc, char * argv[] ) then you could check if
there is a runtime argument and use it as the output file. Much better
than hard-coding it.
 

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

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top