I'm working on a C++ module to read wavefront OBJ files; these are text files with many lines with either 2, 3, or more integer or floating point numbers; separated by spaces or tabs. It's not always possible to know how many numbers there will be in a single line without processing it. The C++ stringstream >> float technique is well suited to this, but it is painfully slow compared to the atof; strtod, possibly even sscanf methods ( the atof method below, even with extra whitespace processing, is 5x faster than stringstream >> float ) ... my problem is, im having to use the 'extra whitespace processing', because none of the C methods seem to show any good indication of whether a number was read, and if so, how much of the string was converted.
My question is mainly about strtod; since it's the only one of those that looks like it could do this, because it lets one pass in a pointer to a char pointer, and that's supposed to point to the 'rest' of the string after a number's been extracted.. however, what happens when it fails? is the value of the char ** passed in as the last argument defined after a failed operation?
I want to be able to say something like:
if( ! pullfloat(str, x ) ) //error;
if( ! pullfloat(str, y ) ) //error;
if( ! pullfloat(str, z ) ) //error;
but also something like:
while( pullfloat(str, f ) ) //dosomething;
I'm using this code atm; but it seems hyper-redundant, since whatever hapens in the loop, I still do an atof, and atof does the same whitespace detection as I'm doing.. any ideas on how I can cut out the whitespace detection, but still get the same information?
int pullfloat( const char ** str_pp, float & f )
{
int started = false;
const char * init = *str_pp;
for( const char * str = init; *str != '\0'; str++, ( *str_pp )++ )
{
char c = *str;
if( ! started ) started = ( ( c != ' ' ) || ( c != '\t') );
else if( ( c == ' ' ) || ( c == '\t' ) ) break;
}
if( started )
{
f = atof( init );
return true;
}
else return false;
}