iostream vs stdio.h

Discussion in 'C++' started by Ningyu Shi, Sep 15, 2006.

  1. Ningyu Shi

    Ningyu Shi Guest

    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
    Ningyu Shi, Sep 15, 2006
    #1
    1. Advertising

  2. 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::eek:stream* OriginalStream;

    decorated_ostream& operator<<(std::eek:stream& (__cdecl *_F)(std::eek:stream&))
    {
    ((*_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::eek:stream& 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
    Stuart Redmann, Sep 15, 2006
    #2
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Vicent

    iostream or stdio

    Vicent, Aug 25, 2003, in forum: C++
    Replies:
    2
    Views:
    1,729
  2. Joona I Palaste

    Re: Output without stdio.h or iostream

    Joona I Palaste, Jul 3, 2003, in forum: C Programming
    Replies:
    0
    Views:
    713
    Joona I Palaste
    Jul 3, 2003
  3. Lew Pitcher

    Re: Output without stdio.h or iostream

    Lew Pitcher, Jul 3, 2003, in forum: C Programming
    Replies:
    0
    Views:
    740
    Lew Pitcher
    Jul 3, 2003
  4. Malcolm

    Re: Output without stdio.h or iostream

    Malcolm, Jul 3, 2003, in forum: C Programming
    Replies:
    0
    Views:
    1,047
    Malcolm
    Jul 3, 2003
  5. Replies:
    18
    Views:
    1,903
    crazzybugger
    Oct 22, 2006
Loading...

Share This Page