468,504 Members | 1,928 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,504 developers. It's quick & easy.

iostream vs stdio.h

I recently started to write a program in c++, which involves some I/O
of file. Quickly, I found that it's difficult to use the c++ iostream
stuff.
say I want to do
printf("%10.3f %.4f %5d",a,b,c)
in c++
is it right to write like
cout<<setprecision(3)<<setw(10)<<a<<........?
that's too complicated...
I've read a lot of old discussion on this group, still confused, is
there a easier way to do my job in c++ way? I just want some simple
controled data output.
is there a way like
cout<<fmt("%10.3f %.4f %5d")<<a<<b<<c?
thanks

Sep 15 '06 #1
1 4834
Ningyu Shi wrote:
I recently started to write a program in c++, which involves some I/O
of file. Quickly, I found that it's difficult to use the c++ iostream
stuff.
say I want to do
printf("%10.3f %.4f %5d",a,b,c)
in c++
is it right to write like
cout<<setprecision(3)<<setw(10)<<a<<........?
that's too complicated...
I've read a lot of old discussion on this group, still confused, is
there a easier way to do my job in c++ way? I just want some simple
controled data output.
is there a way like
cout<<fmt("%10.3f %.4f %5d")<<a<<b<<c?
thanks
What about the following:

#include <iostream>
#include <sstream>
#include <iomanip>

int StringToInt(std::string stringValue)
{
std::stringstream ssStream(stringValue);
int iReturn;
ssStream >iReturn;
return iReturn;
}

class decorated_ostream
{
public:
std::string FormatSpecifier;
std::ostream* OriginalStream;

decorated_ostream& operator<<(std::ostream& (__cdecl *_F)(std::ostream&))
{
((*_F)(*OriginalStream));
return *this;
}
};

class ostream_decorator
{
public:
std::string FormatSpecifier;
};

ostream_decorator fmt (const char* Format)
{
ostream_decorator RetVal;
RetVal.FormatSpecifier = Format;
return RetVal;
}

decorated_ostream operator<< (std::ostream& p_refLHS, ostream_decorator&
Specifier)
{
decorated_ostream RetVal;
RetVal.OriginalStream = &p_refLHS;
RetVal.FormatSpecifier = Specifier.FormatSpecifier;
return RetVal;
}

template <class T>
decorated_ostream& operator<< (decorated_ostream& p_refLHS, T p_RHS)
{
// If the format specifier is zero, we behave just like an ordinary
ostream.
if (p_refLHS.FormatSpecifier.size () == 0)
{
(*p_refLHS.OriginalStream) << p_RHS;
return p_refLHS;
}

// Search the format specifier for the first format specification.
int Temp = p_refLHS.FormatSpecifier.find_first_of ("%");
if (Temp == std::string::npos)
{
// If we haven't found any '%', we can assume that the format
string can be copied to the underlying
// stream one by one.
(*p_refLHS.OriginalStream) << p_refLHS.FormatSpecifier;
p_refLHS.FormatSpecifier.erase ();
return p_refLHS;
}
else
{
// Print the string before the '%' symbol and process the format
specifier.
(*p_refLHS.OriginalStream) << p_refLHS.FormatSpecifier.substr (0,
Temp);
p_refLHS.FormatSpecifier .erase (0, Temp + 1);

// We only process size specifier and precision of floats and doubles.
int Temp = p_refLHS.FormatSpecifier.find_first_not_of ("0123456789");
if (p_refLHS.FormatSpecifier[Temp] == '.' ||
p_refLHS.FormatSpecifier[Temp] == 'd' ||
p_refLHS.FormatSpecifier[Temp] == 'f')
{
// If Temp is non-zero, the user has supplied a width specifier.
if (Temp 0)
{
// Parse the integer value and set it as requested width.
(*p_refLHS.OriginalStream) << std::setw (StringToInt
(p_refLHS.FormatSpecifier.substr (0, Temp)));
p_refLHS.FormatSpecifier.erase (0, Temp);
}
}
else
// TODO: do some meaningful error handling here.
throw 0;

// If there is a point in the format specification, we must search
for a precision specification.
if (p_refLHS.FormatSpecifier[0] == '.')
{
p_refLHS.FormatSpecifier.erase (0, 1);
Temp = p_refLHS.FormatSpecifier.find_first_not_of ("0123456789");
if (p_refLHS.FormatSpecifier[Temp] == 'd' ||
p_refLHS.FormatSpecifier[Temp] == 'f')
{
// If Temp is non-zero, the user has supplied a precision
specifier.
if (Temp 0)
{
// Parse the integer value and set it as requested precision.
(*p_refLHS.OriginalStream) << std::setprecision (StringToInt
(p_refLHS.FormatSpecifier.substr (0, Temp)));
p_refLHS.FormatSpecifier.erase (0, Temp);
}
}
else
// TODO: do some meaningful error handling here.
throw 0;
}

(*p_refLHS.OriginalStream) << p_RHS;
p_refLHS.FormatSpecifier = p_refLHS.FormatSpecifier.erase (0, 1);
return p_refLHS;
}
}

int main ()
{

std::cout << fmt ("test1 %10ftest2 %4.2d") << 3.5 << 3.1416 <<
"test3" << std::endl;
return 0;
}

Above code has some drawbacks, however: only format specifications for
double and floats are recognized, and for these only the width and
precision is parsed. If you should need more, you'd have to modify the
parsing of the format specifiers. Furthermore, no type checking is
performed. This means that a user may specify "%d" but put a string as
next parameter into the decorated_ostream. Of course, you could check
this by retrieving the type of T at run-time and check against the
format specifier. You should keep in mind, that you cannot pass a second
fmt () specification into the call chain, since the second
ostream_decorator would be passed to the underlying stream, but the
resulting new decorated_ostream will be discarded. If you need this
behaviour urgently i'd think of a better solution.

Regards,
Stuart
Sep 15 '06 #2

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

10 posts views Thread by John Tiger | last post: by
2 posts views Thread by Cat | last post: by
11 posts views Thread by Charles L | last post: by
2 posts views Thread by Sigmund Skjelnes | last post: by
4 posts views Thread by goberle | last post: by
5 posts views Thread by Tim Cambrant | last post: by
reply views Thread by NPC403 | last post: by
reply views Thread by fmendoza | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.