stream input

A

Aleks Dubinskiy

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.
 
V

Victor Bazarov

Aleks said:
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
 
M

Mike Wahler

Aleks Dubinskiy said:
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
 
V

Victor Bazarov

Mike said:
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
 
R

Rob Williscroft

Aleks Dubinskiy wrote in in
comp.lang.c++:
Hi folks,
I am well aware of the superiority of using streams and operators << /
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.
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

Aleks said:
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;
}
 
M

Mike Wahler

Victor Bazarov said:
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
 
T

tom_usenet

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
 
D

Dietmar Kuehl

tom_usenet said:
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.
 
A

Aleks Dubinskiy

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.

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
 
O

Old Wolf

Aleks Dubinskiy said:
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.
 

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

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top