extracting an arbitrary number of numbers from a string

Please support our C advertiser: Programming Forums - DaniWeb Sister Site
Reply

Join Date: Jul 2006
Posts: 1,091
Reputation: MattEvans is a jewel in the rough MattEvans is a jewel in the rough MattEvans is a jewel in the rough 
Solved Threads: 63
Moderator
Featured Poster
MattEvans's Avatar
MattEvans MattEvans is offline Offline
Veteran Poster

extracting an arbitrary number of numbers from a string

 
0
  #1
Sep 19th, 2007
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:
  1. if( ! pullfloat(str, x ) ) //error;
  2. if( ! pullfloat(str, y ) ) //error;
  3. if( ! pullfloat(str, z ) ) //error;

but also something like:
  1. 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?
  1. int pullfloat( const char ** str_pp, float & f )
  2. {
  3. int started = false;
  4. const char * init = *str_pp;
  5. for( const char * str = init; *str != '\0'; str++, ( *str_pp )++ )
  6. {
  7. char c = *str;
  8. if( ! started ) started = ( ( c != ' ' ) || ( c != '\t') );
  9. else if( ( c == ' ' ) || ( c == '\t' ) ) break;
  10. }
  11. if( started )
  12. {
  13. f = atof( init );
  14. return true;
  15. }
  16. else return false;
  17. }
Plato forgot the nullahedron..
Reply With Quote Quick reply to this message  
Join Date: Jul 2006
Posts: 1,091
Reputation: MattEvans is a jewel in the rough MattEvans is a jewel in the rough MattEvans is a jewel in the rough 
Solved Threads: 63
Moderator
Featured Poster
MattEvans's Avatar
MattEvans MattEvans is offline Offline
Veteran Poster

Re: extracting an arbitrary number of numbers from a string

 
0
  #2
Sep 19th, 2007
Actually, ignore that. I realised it's not as simple as just looking at whitespace, because in the parts where there IS an arbitrary number of numbers, they are delimited like this:

1/1/1 2/2/4 3/6/4 8/0/1

or sometimes even like this:

1//3 2//4 5//7 etc..

back to the drawing board.. o_O

EDIT: it would still be useful to know if the value of the char ** passed in as the last argument of strtod is defined if a number can't be extracted...?
Last edited by MattEvans; Sep 19th, 2007 at 1:48 am.
Plato forgot the nullahedron..
Reply With Quote Quick reply to this message  
Join Date: Aug 2005
Posts: 15,440
Reputation: Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute 
Solved Threads: 1473
Team Colleague
Featured Poster
Ancient Dragon's Avatar
Ancient Dragon Ancient Dragon is offline Offline
Still Learning

Re: extracting an arbitrary number of numbers from a string

 
0
  #3
Sep 19th, 2007
If the first sequence of non-whitespace characters in str does not form a valid floating-point number as just defined, or if no such sequence exists because either str is empty or contains only whitespace characters, no conversion is performed
http://www.cplusplus.com/reference/c...ib/strtod.html

From the above I don't think the value of the third parameter to strtod() is changed. But the easiest way to find out is to write a small test program and try it out.
Last edited by Ancient Dragon; Sep 19th, 2007 at 2:51 am.
Don't PM me with questions -- you might get a nasty PM in response. If you have a question then post it in one of the forums.
Reply With Quote Quick reply to this message  
Join Date: Jul 2006
Posts: 1,091
Reputation: MattEvans is a jewel in the rough MattEvans is a jewel in the rough MattEvans is a jewel in the rough 
Solved Threads: 63
Moderator
Featured Poster
MattEvans's Avatar
MattEvans MattEvans is offline Offline
Veteran Poster

Re: extracting an arbitrary number of numbers from a string

 
0
  #4
Sep 19th, 2007
I've seen that page, I have it open in a tab already =P The fact it doesn't mention a change is why I was wondering.

The problem with writing a small program to test it out, is that a positive result won't necessarily tell me that it is well defined - it might work on my machine, but not work elsewhere. The best I could prove is that it doesn't work atall... Still; I suppose that's something. I will give it a try, but if it does work, unless I can test it on other machines, or see it in use, or see some document saying it will do that always, I won't feel happy using it.
Plato forgot the nullahedron..
Reply With Quote Quick reply to this message  
Join Date: Jul 2006
Posts: 1,091
Reputation: MattEvans is a jewel in the rough MattEvans is a jewel in the rough MattEvans is a jewel in the rough 
Solved Threads: 63
Moderator
Featured Poster
MattEvans's Avatar
MattEvans MattEvans is offline Offline
Veteran Poster

Re: extracting an arbitrary number of numbers from a string

 
0
  #5
Sep 19th, 2007
Actually, no change is indication that it has failed; since it wouldn't be able to convert a lengthless string to a number.. If it pointed the pointer to something random on failure, that wouldn't be useful.. but I don't think it's very likely to do that...
Plato forgot the nullahedron..
Reply With Quote Quick reply to this message  
Join Date: Aug 2005
Posts: 15,440
Reputation: Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute 
Solved Threads: 1473
Team Colleague
Featured Poster
Ancient Dragon's Avatar
Ancient Dragon Ancient Dragon is offline Offline
Still Learning

Re: extracting an arbitrary number of numbers from a string

 
0
  #6
Sep 19th, 2007
>> it might work on my machine, but not work elsewhere
The behavior has nothing to do with what machine the compiled program is run on. Since strtod() is in C89 standards the function will behave the same on every modern C compiler.
Don't PM me with questions -- you might get a nasty PM in response. If you have a question then post it in one of the forums.
Reply With Quote Quick reply to this message  
Join Date: Jul 2006
Posts: 1,091
Reputation: MattEvans is a jewel in the rough MattEvans is a jewel in the rough MattEvans is a jewel in the rough 
Solved Threads: 63
Moderator
Featured Poster
MattEvans's Avatar
MattEvans MattEvans is offline Offline
Veteran Poster

Re: extracting an arbitrary number of numbers from a string

 
0
  #7
Sep 19th, 2007
Well.. I thought, perhaps, an implementation of strtod might use that pointer to look ahead through the string, in which case, it would get moved forwards even if a number wasn't 'consumed'... Thinking about it right now though, I don't think that's likely, it would be quite silly if that was the case.

Surely any individual apect of the whole behaviour is only guaranteed to work on multiple machines identically if that part of the behaviour's actually defined in the standard? I mean, if it wasn't explicitly in the standard that 'the pointer will be unchanged on failure', implementors of the cstdlib library could be free to implement the internal workings of the function it in their own way [ like the silly way above for example ]; or, is the standard totally rigid - to the level of a mandate for the code in each function rather than a specification for each function?
Plato forgot the nullahedron..
Reply With Quote Quick reply to this message  
Join Date: Aug 2005
Posts: 15,440
Reputation: Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute 
Solved Threads: 1473
Team Colleague
Featured Poster
Ancient Dragon's Avatar
Ancient Dragon Ancient Dragon is offline Offline
Still Learning

Re: extracting an arbitrary number of numbers from a string

 
0
  #8
Sep 19th, 2007
>>or, is the standard totally rigid - to the level of a mandate for the code in each function rather than a specification for each function?
The standards dictate the specifications, what the function is supposed to do. I'm not about to pay $289.00 USD for a copy of the standards so I can not verify exactly what it says or does not say about that function.
Don't PM me with questions -- you might get a nasty PM in response. If you have a question then post it in one of the forums.
Reply With Quote Quick reply to this message  
Join Date: Sep 2004
Posts: 7,728
Reputation: Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute 
Solved Threads: 737
Team Colleague
Narue's Avatar
Narue Narue is offline Offline
Code Goddess

Re: extracting an arbitrary number of numbers from a string

 
1
  #9
Sep 19th, 2007
>I mean, if it wasn't explicitly in the standard that 'the pointer will be unchanged on failure',
>implementors of the cstdlib library could be free to implement the internal workings of the
>function it in their own way
True, but the behavior in this case is carefully specified by the standard. strtod breaks the source string into three parts: leading whitespace (possibly empty), a legal floating-point representation, and trailing unmatched characters (including '\0'). Provided the second argument isn't a null pointer, it's guaranteed to be set to the first character in the third part. If the second part is empty (ie. strtod completely failed to match a floating-point value), the second argument is set to the source string.

You can test these rules fairly easily:
  1. #include <assert.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4.  
  5. const char *check_strtod ( const char *s )
  6. {
  7. const char *end;
  8.  
  9. printf ( "%f\n", strtod ( s, &end ) );
  10.  
  11. return end;
  12. }
  13.  
  14. int main ( void )
  15. {
  16. const char *p;
  17.  
  18. /* Full match, end points to '\0' */
  19. assert ( *check_strtod ( "123.456" ) == '\0' );
  20.  
  21. /* Full match after leading whitespace, end points to '\0' */
  22. assert ( *check_strtod ( " \r\n\t\v\f123.456" ) == '\0' );
  23.  
  24. /* Partial match, end points to unmatched string */
  25. assert ( strcmp ( check_strtod ( "123.456abcdef" ), "abcdef" ) == 0 );
  26.  
  27. /* Partial match after leading whitespace, end points to unmatched string */
  28. assert ( strcmp ( check_strtod ( " 123.456abcdef" ), "abcdef" ) == 0 );
  29.  
  30. /* Complete failure, end points to the source string */
  31. assert ( *check_strtod ( " \r\n\t\v\fabcdef" ) == ' ' );
  32.  
  33. return 0;
  34. }
I'm here to prove you wrong.
Reply With Quote Quick reply to this message  
Join Date: Jul 2006
Posts: 1,091
Reputation: MattEvans is a jewel in the rough MattEvans is a jewel in the rough MattEvans is a jewel in the rough 
Solved Threads: 63
Moderator
Featured Poster
MattEvans's Avatar
MattEvans MattEvans is offline Offline
Veteran Poster

Re: extracting an arbitrary number of numbers from a string

 
0
  #10
Sep 19th, 2007
Well; it's good to know that it will behave like this consistantly. I can't actually use it in the situation with the arbitrary number of numbers; since, as I mentioned, I forgot that I have to deal with blocks of numbers with slashes et al, but, I'm gonna use it for the fixed count space delimited data, it's very fast compared to iostreams, and can detect errors like missing numbers/spaces. My pullfloat is like this now.. neater, less redundant, seems to work correctly.
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3.  
  4. int pullfloat( char ** p_str, double & f )
  5. {
  6. char * str = *p_str;
  7. char ** check = &str;
  8. f = strtod( str, p_str );
  9. return( *check != *p_str );
  10. }
  11.  
  12. int main( void )
  13. {
  14. char * str = "1 2 3 456.0002 789 76.32 99999.888 3662 \n 1535 \t\t \n 1159 1593 1.24e+2 ";
  15. char ** p_str = &str;
  16. double f = 0.0;
  17. while( pullfloat( p_str, f ) ) printf( "Float: %f\n", f );
  18. }

$289.00 USD for the standard documents? That's expensive for something like that..
Plato forgot the nullahedron..
Reply With Quote Quick reply to this message  
Reply

This thread is more than three months old.
Perhaps start a new thread instead?
Message:


Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC