User Name Password Register
DaniWeb IT Discussion Community
All
What is DaniWeb IT Discussion Community?
You're currently browsing the C++ section within the Software Development category of DaniWeb, a massive community of 426,609 software developers, web developers, Internet marketers, and tech gurus who are all enthusiastic about making contacts, networking, and learning from each other. In fact, there are 1,544 IT professionals currently interacting right now! Registration is free, only takes a minute and lets you enjoy all of the interactive features of the site.
Please support our C++ advertiser: Programming Forums

C and C++ Timesaving Tips

Join Date: Sep 2004
Posts: 6,325
Reputation: Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of Narue has much to be proud of 
Rep Power: 28
Solved Threads: 458
Super Moderator
Narue's Avatar
Narue Narue is offline Offline
Expert Meanie

Re: C and C++ Timesaving Tips

  #12  
Apr 7th, 2005
This one is entertaining, and useful too. We all know ("we" being C++ programmers who came from C or still use C extensively) that scanf will eat up a format nice and pretty:
scanf ( "%d-%d-%d", &m, &d, &y );
If the input stream does not contain an integer followed by a '-' followed by an integer (shush Dave, and humor me), followed by a '-' followed by an integer, the call will fail. Sadly, this useful feature isn't available in C++ unless you use scanf. Using iostreams, you would be forced to do something painful like this (with suitable error handling, of course):
cin>> m;
if ( cin.peek() == '-' )
  cin.ignore();
cin>> d;
if ( cin.peek() == '-' )
  cin.ignore();
cin>> y;
Wouldn't it be nice if we could just do this and be done with it?
cin>> m >>"-">> d >>"-">> y;
Well, unfortunately it's not quite that easy. One could overload operator>> for a pointer to const char, but that kind of invades the implementation's personal space and therefore, is not portable.

To do it would be trivial though:
istream& operator>> ( istream& in, const char *s )
{
  while ( *s != '\0' && in && in.peek() == *s ) {
    in.get();
    ++s;
  }

  if ( *s != '\0' )
    in.setstate ( ios::failbit );

  return in;
}
This was my solution (more or less). I didn't need something portable, and the benefit of clarity was a decisive factor. Looking toward portability though, just as a mental exercise, I also considered the manipulator approach:
class scan {
public:
  scan ( const char *init ): fmt ( init ) {}
  friend istream& operator>> ( istream& in, const scan& s )
  {
    while ( *s.fmt != '\0' && in && in.peek() == *s.fmt ) {
      in.get();
      ++s.fmt;
    }

    if ( *s.fmt != '\0' )
      in.setstate ( ios::failbit );

    return in;
  }
private:
  mutable const char *fmt;
};
It's almost as simple, but using it requires a bit more work:
cin>> m >> scan ( "-" ) >> d >> scan ( "-" ) >> y;
On a similar note, I also found a similar manipulator useful. The following manipulator will discard all characters in the stream up to (and including) a user defined character delimiter:
class moveto {
public:
  moveto ( istream::int_type init ): ch ( init ) {}
  friend istream& operator>> ( istream& in, const moveto& d )
  {
    if ( in.rdbuf()->in_avail() > 0 )
      in.ignore ( numeric_limits<streamsize>::max(), d.ch );

    return in;
  }
private:
  istream::int_type ch;
};
This is slightly more complicated than the usual "empty the buffer" call to ignore, designed to flush the stream of interactive input. That job could be performed with a simple moveto request:
cin>> moveto ( '\n' );
But, moveto is useful in parsing as well.

One can easily imagine how useful these manipulators can be. Not only does the scanf behavior of eating a format work with standard input and output, a clever programmer could easily pair them with stringstreams, fstreams, or even custom streams to solve a whole slew of formatted parsing problems without hacking together something big and ugly.

And with a little bit of extra work, the scan manipulator can be extended to more accurately mimic scanf's format processing.
I'm a programmer. My attitude starts with arrogance, holds steady at condescension, and ends with hostility. Get used to it.
 
All times are GMT -4. The time now is 11:38 pm.
Forum system based on vBulletin Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
©2003 - 2008 DaniWeb® LLC