RWCString to long


DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Results 1 to 6 of 6

Thread: RWCString to long

  1. #1
    Join Date
    May 2004
    Posts
    242

    RWCString to long

    Hello,

    I'm trying to convert a RWCString to long.

    I found stringToNum method, but I'm always getting :-

    ...
    Error: The function "stringToNum" must have a prototype.
    ...

    The thing is I'm including the right header file :-

    #include <rw/tools/localesnapshot.h>

    Interestingly enough, I'm including a different H file under the same location #include <rw/tools/regex.h> but that one works.

    I then tried doing it in two steps, i.e. RWCstring to string and then string to a long :-

    RWCString xx = "123456";
    string fff = string(xx);
    long tradeSid = atol(fff.c_str());

    But, that's not very nice.

    Any ideas please ?

    Many thanks.

  2. #2
    Join Date
    Dec 2003
    Posts
    3,366
    Something like this might do it, but it just moves the explicit variable to a hidden temporary.

    atol( ((string)(xx)).c_str() );

    Can you get a char* out of the RWC object? I am not familiar with this class. IF so, should be able to atol it from there, if its null terminated... (?).

  3. #3
    Join Date
    May 2004
    Posts
    242
    Thanks for that Jonnin, but I was hoping to use stringToNum.

    Any ideas please ?

    Thanks.

  4. #4
    Join Date
    Dec 2003
    Posts
    3,366
    I cannot find a reference to a standard function by that name anywhere. Is it part of the rwc library? There are hand-rolled functions of this name on the web, and others have used this name for their libraries and such, but I am coming up short on it (??).



    You can do stuff like this (stolen from the web as well)

    template <class T>
    bool from_string(T& t,
    const std::string& s,
    std::ios_base& (*f)(std::ios_base&))
    {
    std::istringstream iss(s);
    return !(iss >> f >> t).fail();

    from_string<float>(f, std::string("123.456"), std::dec)
    as well, but its a sledgehammer to push in a thumbtack, you have to have stringstreams and strings in the same code block using the same data, which is ugly IMO. Thats the biggest failure of the string class, that you have to have BOTH strings and streamstrings to do what you can with a char array at 4 times the cpu cost, double the memory requirement, etc.


    It sounds like your code is just missing the header for the function you want to use, but I do not know what or where that might be.
    Last edited by jonnin; 09-09-2010 at 02:48 PM.

  5. #5
    Join Date
    Dec 2007
    Posts
    401
    > I found stringToNum method, but I'm always getting :-
    > Error: The function "stringToNum" must have a prototype.
    > The thing is I'm including the right header file :-
    > #include <rw/tools/localesnapshot.h>

    IIRC, stringToNum is a non-static member of RWLocale. You need to do something like this:
    Code:
    #include <locale.h>
    #include <rw/locale.h>
    
        ....
        RWAnsiLocale loc ;
        double number ;
        RWString str = "123.45" ;
        if( loc.stringToNum( str, &number )
        {
            // use number
        }
        else
        {
            // error
        }
        ....
    > I then tried doing it in two steps, i.e. RWCstring to string and then string to a long :-
    > RWCString xx = "123456";
    > string fff = string(xx);
    > long tradeSid = atol(fff.c_str());

    RWCString is a thin wrapper over std::string; you can call c_str() on it directly without constructing a temporary std::string from it.


    > But, that's not very nice.

    Using atoi, atol or atoll is never nice - just avoid the use of these functions alltogether. Error handling is impossible; does the string hold a valid sequence of digits that represents the number 0, or an invalid sequence of chars? In many implementations, these functions are neither thread safe nor async-cancel safe. In C code, prefer using strtol, which was added to ISO C89 as a better-behaved replacement for these badly designed functions.

    Unless you need to perform a millions or so of these conversions every second, just use the more elegant, far less error prone C++ techniques. Use a std::istringstream for the conversion or better still just use boost::lexical_cast<>, which give more than adequate performance in almost all cases.

    Here are some actual numbers (FreeBSD 8.1, Intel Core2 Duo T7100 @1.80GHz, g++ (GCC) 4.5.1, compiled with -Wall -std=c++98 -pedantic -Werror -O3 -I /usr/local/include)

    Code:
    #include <cctype>
    #include <string>
    #include <stdexcept>
    #include <cstdio>
    #include <errno.h>
    #include <sstream>
    #include <boost/lexical_cast.hpp>
    #include <ctime>
    #include <iomanip>
    #include <cstdlib>
    #include <vector>
    #include <iostream>
    
    struct naive
    {
        inline long operator() ( const std::string& str ) const
        {
            long result = 0 ;
            const char* cstr = str.c_str() ;
            while( std::isspace(*cstr) ) ++cstr ;
    
            bool negative = *cstr == '-' ;
            if( negative || ( *cstr == '+' ) )
            {
                ++cstr ;
                while( std::isspace(*cstr) ) ++cstr ;
            }
    
            while( *cstr >= '0' && *cstr <= '9')
            {
                static const long max_val = std::numeric_limits<long>::max() ;
                if( result > (  max_val/10 - (*cstr - '0') ) )
                        throw std::length_error( "long int overflow" ) ;
                result = (result*10) + (*cstr - '0') ;
                ++cstr;
            }
    
            if( *cstr != 0 ) throw std::invalid_argument( "not a long int" ) ;
            return negative ? result : -result ;
        }
    };
    
    struct c_strtol
    {
        inline long operator() ( const std::string& str ) const
        {
            errno = 0 ;
            char* end = 0 ;
            long result = std::strtol( str.c_str(), &end, 10 ) ;
    
            if( !end || (*end != 0) || ( errno != 0 ) )
                   throw std::invalid_argument( "not a long int" ) ;
            return result ;
        }
    };
    
    struct c_sscanf
    {
        inline long operator() ( const std::string& str ) const
        {
            long result ;
            char test ;
            errno = 0 ;
            int nread = std::sscanf( str.c_str(), "&#37;ld %c", &result, &test ) ;
    
            if( ( nread != 1 ) || ( errno != 0 ) )
                     throw std::invalid_argument( "not a long int" ) ;
            return result ;
        }
    };
    
    template< typename T > struct naive_stream
    {
        inline T operator() ( const std::string& str ) const
        {
            std::istringstream stm(str) ;
            T result ;
            if( !( stm >> result ) || !stm.eof() )
                       throw std::invalid_argument( "not a long int" ) ;
            return result ;
        }
    };
    
    template< typename T > struct lexical_cast
    {
        inline T operator() ( const std::string& str ) const
        { return boost::lexical_cast<T>(str) ; }
    };
    
    template< typename FN >
    void profile( const std::vector<std::string> vec,
                          int repeat, FN function, const char* description )
    {
        std::cout << description << ": " ;
    
        std::clock_t start = std::clock() ;
        for( int i=0 ; i<repeat ; ++i )
             for( std::size_t j=0 ; j<vec.size() ; ++j )
                  function( vec[j] ) ;
        std::clock_t end = std::clock() ;
    
        std::size_t count = vec.size() * repeat ;
        double secs = double(end-start) / CLOCKS_PER_SEC ;
        std::cout << std::fixed << std::setprecision(2)
                  << count/secs / 1000000 << " million per second.\n" ;
    }
    
    #define PROFILE(a,b,c) profile( a, b, c, #c ) ;
    
    int main()
    {
        enum { N = 1024*1024, NBY2 = N/2, REPEAT = 16 } ;
        std::vector<std::string> number_strings ;
        number_strings.reserve(N) ;
    
        int mid = RAND_MAX / 2 ;
        sranddev() ; // unix
        for( int i = -NBY2 ; i < NBY2 ; ++i )
            number_strings.push_back(
                   boost::lexical_cast<std::string>( std::rand() - mid ) ) ;
    
        PROFILE( number_strings, REPEAT, naive() ) ;
        PROFILE( number_strings, REPEAT, c_strtol() ) ;
        PROFILE( number_strings, REPEAT, c_sscanf() ) ;
        PROFILE( number_strings, REPEAT, naive_stream<long>() ) ;
        PROFILE( number_strings, REPEAT, lexical_cast<long>() ) ;
    }
    naive(): 13.51 million per second.
    c_strtol(): 9.22 million per second.
    c_sscanf(): 1.27 million per second.
    naive_stream<long>(): 1.03 million per second.
    lexical_cast<long>(): 1.50 million per second.
    Premature (more often than not unnecessary) optimization is the root of all evil.
    Last edited by vijayan; 09-11-2010 at 03:47 AM.

  6. #6
    Join Date
    Dec 2003
    Posts
    3,366
    Nice comparison. If you really and truly had to grind out billions upon billions of these, even the fast & loose one can be cranked up several notches (I would guess 20+ mill per second if totally discard all safety (IE data from a huge file, known to be safe). But that seems like a very odd thing to have to do; bulk data is usually stored in binary anyway and this sort of thing is more often a way to get a number typed by a user (put into a string for self defense), so it does not usually matter.

    The task still falls into the "you cannot do that without 2 classes" problem of c++. Year after year they tweak this language and we still do not have a good string class, sort of funny, in a not funny way. Here, the best of the examples requires using a nonstandard library (boost) which gives short code & the best performance of the cleaner code examples. The second best option is to use C functions. Ouch.

Similar Threads

  1. Search System Tray
    By MyPlague in forum .NET
    Replies: 2
    Last Post: 03-20-2006, 06:18 PM
  2. AnimateWindow API
    By Tim Manos in forum VB Classic
    Replies: 4
    Last Post: 10-19-2001, 07:06 AM
  3. How do I detect an FTP timeout?
    By Julian Milano in forum VB Classic
    Replies: 2
    Last Post: 08-11-2000, 01:11 PM
  4. How do I detect an FTP timeout?
    By Julian Milano in forum VB Classic
    Replies: 0
    Last Post: 08-10-2000, 10:16 PM
  5. Trying to print a PDF File from VB
    By Kunal Sharma in forum VB Classic
    Replies: 2
    Last Post: 04-25-2000, 04:45 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center