C++ how to parse integers (and possibly doubles) from character array (or std::string)?
i am working on simple program and have stuck with this for a few days now.
How to parse integers (and possibly doubles) from character array? If it would be easier, char array can be converted to string, i mean, it is not a must have char array.
I was looking for a C++ way of
sscanf(mystring, "di %lf %lf %lf", &d1, &d2, &d3);
Problem is, i will have multiple lines of unknown length (numbers). And i'll have spaces or comm开发者_如何学编程as or something else delimiting numbers.
Are tokens the way? Of which i know nothing.
Well, thanks for any help.
I'm not too sure what you really need. It sounds like you don't
know the exact format of your file. (You've certainly not
described anything "exact".) To convert integers or doubles
from a string, you should to use istringstream
. If you want
to support a variety of separators, you could easily write
a manipulator to do it, something like:
class skipSeparators
{
std::string mySeparators;
public:
skipSeparators( std::string const& separators )
: mySeparators( separators )
{
}
friend std::ostream&
operator>>(
std::ostream& source,
SkipSeparators const& manip )
{
source >> std::ws;
int next = source.peek();
if ( next != EOF
&& std::find( mySeparators.begin(),
mySeparators.end(),
static_cast<char>( next )
) != mySeparators.end() ) {
source.get();
}
return source;
}
};
With this, you could write something like:
while ( input >> skipSeparators( ",;" ) >> someDouble ) {
// process some double...
}
If knowing where the line ends were important, you can read the
file using getline()
, and create an istringstream
for each
line, using the above on it.
Simple C++ parsers usually look something like this…
struct syntax_error : std::runtime_error {
syntax_error( char const *str ) : std::runtime_error( str ) {}
};
std::istringstream iss( str ); // str is char*; use str.c_str() for std::string
std::string opcode;
long double args[ args_max ];
iss >> opcode; // read up to whitespace
for ( size_t arg_cnt = 0; arg_cnt < arg_counts[ opcode ]; ++ arg_cnt ) {
if ( iss >> args[ arg_cnt ] ) { // read number, discard preceding whitespace
throw syntax_error( "too few args" );
}
char delim;
if ( ! ( iss >> delim ) || delim != ',' ) {
throw syntax_error( "expected ',' delimiter" );
}
}
Take a look at Boost's lexical_cast
, I think it does exactly what you want. Example from link:
int main(int argc, char * argv[])
{
using boost::lexical_cast;
using boost::bad_lexical_cast;
std::vector<short> args;
while(*++argv)
{
try
{
args.push_back(lexical_cast<short>(*argv));
}
catch(bad_lexical_cast &)
{
args.push_back(0);
}
}
...
}
精彩评论