stream input

Discussion in 'C++' started by Aleks Dubinskiy, Aug 24, 2004.

  1. Hi folks,
    I am well aware of the superiority of using streams and operators << / >>
    instead of the old-style printf and scanf. However, there is only one
    obstacle that prevents me from switching to the better form.
    scanf has the following really convenient syntax:

    fscanf(pFile, "prfl num: %d\n", &nPrflNum);
    The convenient part about it is that it's almost an exact copy of the
    fprintf operation that created the input. In particular it allows to skip
    over a particular text by just writing what it is.

    It seems to be very difficult to replace this with a convenient input stream
    version, such as:
    input>>"prfl num: ">>nPrflNum;

    This code turns out to be illegal, because the input stream class doesn't
    know how to input constant strings. The workaround I know for this is quite
    cumbersome, involving reading characters one by one, and verifying if they
    fit the pattern "prfl num: ", or ignoring everything until a numeric
    character is found in the stream.

    Is there a more straightforward / painless way to do what I want?

    Cheers,
    Aleks D.
     
    Aleks Dubinskiy, Aug 24, 2004
    #1
    1. Advertising

  2. Aleks Dubinskiy wrote:
    > Hi folks,
    > I am well aware of the superiority of using streams and operators << / >>
    > instead of the old-style printf and scanf. However, there is only one
    > obstacle that prevents me from switching to the better form.
    > scanf has the following really convenient syntax:
    >
    > fscanf(pFile, "prfl num: %d\n", &nPrflNum);
    > The convenient part about it is that it's almost an exact copy of the
    > fprintf operation that created the input. In particular it allows to skip
    > over a particular text by just writing what it is.
    >
    > It seems to be very difficult to replace this with a convenient input stream
    > version, such as:
    > input>>"prfl num: ">>nPrflNum;
    >
    > This code turns out to be illegal, because the input stream class doesn't
    > know how to input constant strings. The workaround I know for this is quite
    > cumbersome, involving reading characters one by one, and verifying if they
    > fit the pattern "prfl num: ", or ignoring everything until a numeric
    > character is found in the stream.
    >
    > Is there a more straightforward / painless way to do what I want?



    Probably something in line with

    template<class S> S& skipover(S& s, const char* str) {
    return s.seekg(fpos(strlen(str), S::cur);
    }
    ...
    skipover(input, "prfl num: ") >> nPrflNum;

    I am sure folks will correct me where I erred.

    V
     
    Victor Bazarov, Aug 24, 2004
    #2
    1. Advertising

  3. Aleks Dubinskiy

    Mike Wahler Guest

    "Aleks Dubinskiy" <> wrote in message
    news:cgfio5$v5v$-c.dk...
    > Hi folks,
    > I am well aware of the superiority of using streams and operators << / >>
    > instead of the old-style printf and scanf. However, there is only one
    > obstacle that prevents me from switching to the better form.
    > scanf has the following really convenient syntax:
    >
    > fscanf(pFile, "prfl num: %d\n", &nPrflNum);
    > The convenient part about it is that it's almost an exact copy of the
    > fprintf operation that created the input. In particular it allows to skip
    > over a particular text by just writing what it is.
    >
    > It seems to be very difficult to replace this with a convenient input

    stream
    > version, such as:
    > input>>"prfl num: ">>nPrflNum;
    >
    > This code turns out to be illegal, because the input stream class doesn't
    > know how to input constant strings. The workaround I know for this is

    quite
    > cumbersome, involving reading characters one by one, and verifying if they
    > fit the pattern "prfl num: ", or ignoring everything until a numeric
    > character is found in the stream.
    >
    > Is there a more straightforward / painless way to do what I want?
    >
    > Cheers,
    > Aleks D.


    std::ifstream input;
    std::string s;
    int num(0);
    /* etc */
    std::getline(input, s);
    if(s == "prfl num: ")
    input >> num;

    -Mike

    >
    >
     
    Mike Wahler, Aug 24, 2004
    #3
  4. Mike Wahler wrote:
    > "Aleks Dubinskiy" <> wrote in message
    > news:cgfio5$v5v$-c.dk...
    >
    >>Hi folks,
    >>I am well aware of the superiority of using streams and operators << / >>
    >>instead of the old-style printf and scanf. However, there is only one
    >>obstacle that prevents me from switching to the better form.
    >>scanf has the following really convenient syntax:
    >>
    >>fscanf(pFile, "prfl num: %d\n", &nPrflNum);
    >>The convenient part about it is that it's almost an exact copy of the
    >>fprintf operation that created the input. In particular it allows to skip
    >>over a particular text by just writing what it is.
    >>
    >>It seems to be very difficult to replace this with a convenient input

    >
    > stream
    >
    >>version, such as:
    >>input>>"prfl num: ">>nPrflNum;
    >>
    >>This code turns out to be illegal, because the input stream class doesn't
    >>know how to input constant strings. The workaround I know for this is

    >
    > quite
    >
    >>cumbersome, involving reading characters one by one, and verifying if they
    >>fit the pattern "prfl num: ", or ignoring everything until a numeric
    >>character is found in the stream.
    >>
    >>Is there a more straightforward / painless way to do what I want?
    >>
    >>Cheers,
    >>Aleks D.

    >
    >
    > std::ifstream input;
    > std::string s;
    > int num(0);
    > /* etc */
    > std::getline(input, s);
    > if(s == "prfl num: ")
    > input >> num;


    I am not sure how it would help to read the integer in a line like

    prfl num: 42

    (which was printed by the symmetrical statement

    of << "prfl num: " << some_int_with_value_42 << std::endl;
    }

    Wouldn't 'getline' skip over the number and read until the end of line
    thus losing the "42"?

    Victor
     
    Victor Bazarov, Aug 24, 2004
    #4
  5. Aleks Dubinskiy wrote in news:cgfio5$v5v$-c.dk in
    comp.lang.c++:

    > Hi folks,
    > I am well aware of the superiority of using streams and operators << /
    > >> instead of the old-style printf and scanf. However, there is only

    > one obstacle that prevents me from switching to the better form.
    > scanf has the following really convenient syntax:
    >
    > fscanf(pFile, "prfl num: %d\n", &nPrflNum);
    > The convenient part about it is that it's almost an exact copy of the
    > fprintf operation that created the input. In particular it allows to
    > skip over a particular text by just writing what it is.
    >
    > It seems to be very difficult to replace this with a convenient input
    > stream version, such as:
    > input>>"prfl num: ">>nPrflNum;
    >
    > This code turns out to be illegal, because the input stream class
    > doesn't know how to input constant strings. The workaround I know for
    > this is quite cumbersome, involving reading characters one by one, and
    > verifying if they fit the pattern "prfl num: ", or ignoring everything
    > until a numeric character is found in the stream.
    >
    > Is there a more straightforward / painless way to do what I want?


    I'm sure there are problems with it, but hopefully it will
    get you started:

    #include <iostream>
    #include <ostream>
    #include <istream>
    #include <sstream>
    #include <string>

    template < typename Ch >
    struct matcher
    {
    Ch const *m_to;
    matcher( Ch const *s ) : m_to( s ) {}
    };

    template < typename Ch, typename Tr >
    std::basic_istream< Ch, Tr > &operator >> (
    std::basic_istream< Ch, Tr > &is, matcher< Ch > const &m
    )
    {
    std::istringstream iss( m.m_to );

    std::string get, got;

    while (iss >> get)
    {
    if ( !(is >> got) ) return is;
    if ( get != got )
    {
    is.setstate( std::ios::failbit );
    return is;
    }
    }

    return is;
    }

    template < typename Ch >
    inline matcher< Ch > match( Ch const *s )
    {
    return matcher< Ch >( s );
    }


    int main()
    {
    std::stringstream ss;
    int i = 10, j = -1;

    ss << "i: " << i << '\n';

    ss >> match( "i: " ) >> j;

    std::cout << j << '\n';

    ss.clear();

    ss.str( "i : 2" );

    if ( ss >> match( "i: " ) )
    {
    ss >> j;
    }
    else
    {
    std::cout << "input didn't match\n";
    }
    }


    Rob.
    --
    http://www.victim-prime.dsl.pipex.com/
     
    Rob Williscroft, Aug 24, 2004
    #5
  6. Aleks Dubinskiy wrote:

    > fscanf(pFile, "prfl num: %d\n", &nPrflNum);
    > The convenient part about it is that it's almost an exact copy of the
    > fprintf operation that created the input. In particular it allows to skip
    > over a particular text by just writing what it is.
    >
    > It seems to be very difficult to replace this with a convenient input
    > stream version, such as:
    > input>>"prfl num: ">>nPrflNum;


    Something like that can do the work:

    #include <istream>
    #include <string>

    class Literal {
    public:
    Literal (const std::string & nstr) :
    str (nstr)
    { }
    friend std::istream & operator >>
    (std::istream & is, const Literal & lit);
    private:
    std::string str;
    };

    std::istream & operator >> (std::istream & is, const Literal & lit)
    {
    for (std::string::size_type i= 0; i < lit.str.size (); ++i)
    {
    char c= is.get ();
    if (! is)
    break;
    if (c != lit.str )
    {
    is.unget ();
    is.clear (std::ios::badbit);
    break;
    }
    }
    return is;
    }

    Little test:

    #include <iostream>
    #include "literal.h"

    int main ()
    {
    int i;
    std::cin >> Literal ("Hello ") >> i;
    std::cout << i << std::endl;
    }

    --
    Salu2
     
    =?ISO-8859-15?Q?Juli=E1n?= Albo, Aug 24, 2004
    #6
  7. Aleks Dubinskiy

    Mike Wahler Guest

    "Victor Bazarov" <> wrote in message
    news:DIIWc.231$09.us.to.verio.net...
    > Mike Wahler wrote:
    > > "Aleks Dubinskiy" <> wrote in message
    > > news:cgfio5$v5v$-c.dk...
    > >
    > >>Hi folks,
    > >>I am well aware of the superiority of using streams and operators << /

    >>
    > >>instead of the old-style printf and scanf. However, there is only one
    > >>obstacle that prevents me from switching to the better form.
    > >>scanf has the following really convenient syntax:
    > >>
    > >>fscanf(pFile, "prfl num: %d\n", &nPrflNum);
    > >>The convenient part about it is that it's almost an exact copy of the
    > >>fprintf operation that created the input. In particular it allows to

    skip
    > >>over a particular text by just writing what it is.
    > >>
    > >>It seems to be very difficult to replace this with a convenient input

    > >
    > > stream
    > >
    > >>version, such as:
    > >>input>>"prfl num: ">>nPrflNum;
    > >>
    > >>This code turns out to be illegal, because the input stream class

    doesn't
    > >>know how to input constant strings. The workaround I know for this is

    > >
    > > quite
    > >
    > >>cumbersome, involving reading characters one by one, and verifying if

    they
    > >>fit the pattern "prfl num: ", or ignoring everything until a numeric
    > >>character is found in the stream.
    > >>
    > >>Is there a more straightforward / painless way to do what I want?
    > >>
    > >>Cheers,
    > >>Aleks D.

    > >
    > >
    > > std::ifstream input;
    > > std::string s;
    > > int num(0);
    > > /* etc */
    > > std::getline(input, s);
    > > if(s == "prfl num: ")
    > > input >> num;

    >
    > I am not sure how it would help to read the integer in a line like
    >
    > prfl num: 42
    >
    > (which was printed by the symmetrical statement
    >
    > of << "prfl num: " << some_int_with_value_42 << std::endl;
    > }
    >
    > Wouldn't 'getline' skip over the number and read until the end of line
    > thus losing the "42"?


    Yes, I totally fouled that one up. Thanks for noticing. :)

    std::getline(input, s, ':');
    if(s == "prfl num")
    /* etc */



    -Mike
     
    Mike Wahler, Aug 24, 2004
    #7
  8. Aleks Dubinskiy

    tom_usenet Guest

    On 24 Aug 2004 08:22:48 -0700, "Dietmar Kuehl"
    <> wrote:

    >std::cin >> expect("expect: ") >> whatever;


    Dietmar, any chance of you proposing something like this for
    standardization? The lack of ability to match the fscanf feature-set
    is definitely an embarrassment of iostreams. And <iomanip> is a bit
    bare at the moment...

    Tom
     
    tom_usenet, Aug 24, 2004
    #8
  9. tom_usenet wrote:
    > On 24 Aug 2004 08:22:48 -0700, "Dietmar Kuehl"
    > <> wrote:
    >
    >>std::cin >> expect("expect: ") >> whatever;

    >
    > Dietmar, any chance of you proposing something like this for
    > standardization?


    I hacked this up in less than five minutes and it was only about
    the second or third time I ever needed it. Actually, I don't
    think I have ever used something like this in any production code.
    Thus: is this something really needed?

    Personally, I'm not that interested in doing micro-proposals like
    this for the IOStreams library: if there is something to propose,
    it would be a general overhaul of the IOStreams library. But I don't
    even see much point in this: persistance is done through data bases,
    user interaction through GUIs, and the remaining debug output (this
    is nearly the exclusive use I have myself for IOStreams in production
    code) or input from files is already reasonably handled. It would be
    much more reasonable to concentrate e.g. on XML support of C++.

    However, support for something like the "expect" manipulator mentioned
    here my be a reasonable but small contribution to Boost which may
    make it into a proposal for extensions to the IOStreams library.
    --
    <mailto:> <http://www.dietmar-kuehl.de/>
    <http://www.contendix.com> - Software Development & Consulting
     
    Dietmar Kuehl, Aug 24, 2004
    #9
  10. > I hacked this up in less than five minutes and it was only about
    > the second or third time I ever needed it. Actually, I don't
    > think I have ever used something like this in any production code.
    > Thus: is this something really needed?
    >
    > Personally, I'm not that interested in doing micro-proposals like
    > this for the IOStreams library: if there is something to propose,
    > it would be a general overhaul of the IOStreams library. But I don't
    > even see much point in this: persistance is done through data bases,
    > user interaction through GUIs, and the remaining debug output (this
    > is nearly the exclusive use I have myself for IOStreams in production
    > code) or input from files is already reasonably handled. It would be
    > much more reasonable to concentrate e.g. on XML support of C++.
    >
    > However, support for something like the "expect" manipulator mentioned
    > here my be a reasonable but small contribution to Boost which may
    > make it into a proposal for extensions to the IOStreams library.
    > --
    > <mailto:> <http://www.dietmar-kuehl.de/>
    > <http://www.contendix.com> - Software Development & Consulting


    Thanks for the suggestion, Dietmar - this is exactly what i was looking for.
    While the code is not incredibly difficult, it is still serious and
    unnecessary micro-management.
    I think a lot of people would benefit from this feature in C++, especially a
    portable one!

    Cheers,
    Aleks
     
    Aleks Dubinskiy, Aug 25, 2004
    #10
  11. Aleks Dubinskiy

    Old Wolf Guest

    "Aleks Dubinskiy" <> wrote:
    > Hi folks,
    > I am well aware of the superiority of using streams and operators << / >>
    > instead of the old-style printf and scanf. However, there is only one
    > obstacle that prevents me from switching to the better form.
    > scanf has the following really convenient syntax:
    > fscanf(pFile, "prfl num: %d\n", &nPrflNum);
    > It seems to be very difficult to replace this with a convenient input stream
    > version, such as:
    > input>>"prfl num: ">>nPrflNum;
    >
    > Is there a more straightforward / painless way to do what I want?


    You could use the very flexible Boost Spirit library (www.boost.org)
    (warning - late-model compiler required):

    #include <iostream>
    #include <string>
    #include "boost/spirit/core.hpp"

    using namespace boost::spirit;

    int main()
    {
    std::string s;
    int i;

    getline(std::cin, s);

    if (parse(s.c_str(), "prfl num:" >> int_p[assign_a(i)], space_p).full)
    std::cout << "input was: " << i << "\n";
    else
    std::cout << "input did not match expected form.\n";

    return 0;
    }

    "int_p" indicates to parse a signed int, "[assign_a(i)]" means to
    assign the result of parsing to the variable "i", "space_p"
    indicates that whitespace is used to separate tokens in the input,
    "full" means that the entire input was parsed correctly.
     
    Old Wolf, Aug 25, 2004
    #11
    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. Rasmusson, Lars
    Replies:
    1
    Views:
    771
    popov
    Apr 30, 2004
  2. Replies:
    9
    Views:
    649
    Alex Buell
    Apr 27, 2006
  3. Alexander Korsunsky

    get stream mode flags from an opened stream

    Alexander Korsunsky, Feb 17, 2007, in forum: C++
    Replies:
    1
    Views:
    462
    John Harrison
    Feb 17, 2007
  4. dolphin
    Replies:
    6
    Views:
    568
    Thomas Fritsch
    Mar 18, 2007
  5. Kashif Ur Rehman
    Replies:
    2
    Views:
    878
    Tom Hawtin
    May 17, 2007
Loading...

Share This Page