Re: Parsing (a Series of) Variables
 
Rui Maciel <rui.maciel@gmail.com> writes:
It looks like a job for a proper parser.  Any solution which can be pulled 
together with sscanfs and the sort will inevitable be broken and fallible.
  The following code uses a simplistic parser to parse numbers from
"1 2. .3 4"
  into a heterogenous target, so that
for( numval * v : target )
::std::cout << static_cast< ::std::string >( *v )<< '\n';
  prints
( int )1
( double )2.000000
( double )0.300000
( int )4
  and 
double sum = 0; for( numval * v : target )sum += *v;
::std::cout << sum << '\n';
  prints
7.3
  . I am not sure whether my use of dynamic_cast is correct since it's
  the first time that I actually used it.
#include <iostream>
#include <ostream>
#include <sstream>
#include <vector>
#include <cstdio>
#include <cctype>
#include <string>
struct numval
{ virtual ::std::string text() const = 0; 
  virtual operator ::std::string() const = 0; 
  virtual operator double() const = 0;};
struct intval : public numval
{ int val;
  intval( ::std::string & text )
  { val = ::std::stoi( text ); }
  virtual operator double() const
  { return this->val; }
  virtual operator ::std::string() const
  { return text(); }
  ::std::string text() const
  { ::std::string s;
    s += "( int )";
    s += ::std::to_string( this->val );
    return s; }};
struct doubleval : public numval
{ double val;
  doubleval( ::std::string & text )
  { val = ::std::stod( text ); }
  virtual operator double() const
  { return this->val; }
  virtual operator ::std::string() const
  { return text(); }
  ::std::string text() const
  { ::std::string s;
    s += "( double )";
    s += ::std::to_string( this->val );
    return s; }};
numval * new_numval
( bool point, ::std::string & text )
{ return point ? dynamic_cast< numval * >( new doubleval( text )): 
  dynamic_cast< numval * >( new intval( text )); }
void numeral
( ::std::stringstream & source,
  ::std::string & seen,
  ::std::vector<numval *> & target )
{ int c;
  bool looping = true;
  bool point = false;
  while( looping )
  { c = source.peek();
    if( c == EOF )looping = false; else
    if( isdigit( c ))seen.push_back( source.get() );
    else if( c == '.' )
    { if( point )looping = false; else
      { point = true; seen.push_back( source.get() ); }}
    else looping = false; }
  if( seen == "." )seen.push_back( '0' );
  target.push_back( new_numval( point, seen ));
  seen.clear(); }
void other
( ::std::stringstream & source,
  ::std::string & seen,
  ::std::vector<numval *> & target )
{ int c = source.peek();
  while( !( isdigit( c )|| c == '.' ))
  { seen.push_back( source.get() ); 
    c = source.peek(); }
  seen.clear(); }
int main()
{ ::std::stringstream source{ "1 2. .3 4" };
  ::std::string seen;
  ::std::vector<numval *> target;
  int c; do
  { c = source.peek();
    if( isdigit( c ) || c == '.' )numeral( source, seen, target );
    else                          other(   source, seen, target ); }
  while( source.good() ); 
  for( numval * v : target )
  ::std::cout << static_cast< ::std::string >( *v )<< '\n';
  double sum = 0;
  for( numval * v : target )sum += *v;
  ::std::cout << sum << '\n'; }