String to double conversion - Part 2

Discussion in 'C++' started by Evyn, Oct 10, 2007.

  1. Evyn

    Evyn Guest

    Hi all,

    I have recently asked for advice:
    http://groups.google.com/group/comp...1b/e63d8f10b51f015c?lnk=raot#e63d8f10b51f015c

    My task is to convert a string of characters to a double. The string
    is read from a file and will be in the format 12345. The double output
    must be 0.12345.

    My answer to this problem was:

    double convert(string s)
    {
    return atof((string(".") + s).c_str());
    }

    The prof. was happy, but he told me to write my own atof. So I have
    converted the string to an array of char. Is this the right strategy?
    If so, how to I actually convert the array to a double? (As you no
    doubt can see, I am pretty much in the dark here).

    double stof(string s)
    {
    // c_str - Returns a pointer to a null-terminated array of
    characters representing the string's contents.

    const char* p = s.c_str();
    int len = strlen(p); // get length
    char sArr[len];
    memcpy(sArr, s.c_str(), len); // copy to char array

    double tmp;
    for(int i = 0;i<len;i++)
    {
    cout << endl << i << " = " << sArr; // gives expected
    output
    tmp = (sArr - 48); // gives expected number

    }
    return tmp;
    }


    Regards,
    Jim
    Evyn, Oct 10, 2007
    #1
    1. Advertising

  2. On Oct 10, 12:03 pm, Evyn <> wrote:
    > Hi all,
    >
    > The prof. was happy, but he told me to write my own atof. So I have
    > converted the string to an array of char. Is this the right strategy?


    No - see below.

    > If so, how to I actually convert the array to a double? (As you no
    > doubt can see, I am pretty much in the dark here).
    >
    > double stof(string s)


    Don't pass strings by value, you may incur needless
    copying; use const string& s

    > {
    > const char* p = s.c_str();
    > int len = strlen(p); // get length
    > char sArr[len];
    > memcpy(sArr, s.c_str(), len); // copy to char array
    >

    Apart from the fact that defining a variable-length
    automatic array is non-standard, the above lines are
    pointless; why are you *copying* the data ?

    > double tmp;
    > for(int i = 0;i<len;i++)
    > {
    > cout << endl << i << " = " << sArr; // gives expected
    > tmp = (sArr - 48); // gives expected number
    > }
    > return tmp;
    >
    > }


    Your loop should then become:
    for (int i = 0; i < s.size() ; ++i) {
    int itmp = s - '0';
    :
    }
    On each iteration itmp contains the integer value of
    the character, eg '0' => 0, '1' => 1 etc (assuming
    that string genuinely only contains digits)
    You now need to figure out how to build up a double
    from this. One way would be to divide itmp by
    increasing powers of 10.0 and add the result to
    an accumulator variable.
    tragomaskhalos, Oct 10, 2007
    #2
    1. Advertising

  3. Evyn wrote:
    ....
    > The prof. was happy, but he told me to write my own atof. So I have
    > converted the string to an array of char. Is this the right strategy?


    No need.

    > If so, how to I actually convert the array to a double? (As you no
    > doubt can see, I am pretty much in the dark here).


    The basis for lexical analysis is "state machine". Think about what a
    floating point number looks like.

    +1.e-3
    -.3
    +.0e0
    1e-1
    ..1
    1

    - starts with optional + or -
    - either of -
    digits
    -or-
    "." digits
    -or-
    digits "." digits
    - the optionally
    "e" or "E" followed by optional "+" or "-" followed by digits


    state machine would look like:

    state_0
    \+ -> state_1
    \- -> state_1
    \. -> state_2
    0-9 -> state_3
    {eof} -> state_4
    state_4
    FINAL
    No transitions for this dfa state
    state_1
    \. -> state_2
    0-9 -> state_3
    state_3
    ACCEPT
    \. -> state_5
    0-9 -> state_3
    E -> state_6
    e -> state_6
    state_10
    ACCEPT
    0-9 -> state_10
    E -> state_6
    e -> state_6
    state_5
    ACCEPT
    0-9 -> state_9
    E -> state_6
    e -> state_6
    state_9
    ACCEPT
    0-9 -> state_9
    E -> state_6
    e -> state_6
    state_2
    0-9 -> state_10
    state_8
    ACCEPT
    0-9 -> state_8
    state_6 (exponent)
    \+ -> state_7
    \- -> state_7
    0-9 -> state_8
    state_7 (exponent)
    0-9 -> state_8


    That's an 11 state state machine.

    The basic algorithm is:

    state = state_0;
    double last_accepted_value = 0;
    has_accepted = false;

    while ( has_another_char )
    {
    ch = next_value;

    switch( state )
    {

    .... set the "has_acceppted" flag and the accept value if it is an
    accepted state
    }
    }

    if (has_accepted)
    {
    return accpeted value;
    }

    throw or something.

    It's a really rough explanation so I hope it helps but it should give
    you an idea of the kind of books you can read or other examples you can
    look at.
    Gianni Mariani, Oct 10, 2007
    #3
  4. Evyn

    osmium Guest

    "Gianni Mariani" writes:

    > Evyn wrote:
    > ...
    >> The prof. was happy, but he told me to write my own atof. So I have
    >> converted the string to an array of char. Is this the right strategy?

    >
    > No need.
    >
    >> If so, how to I actually convert the array to a double? (As you no
    >> doubt can see, I am pretty much in the dark here).

    >
    > The basis for lexical analysis is "state machine". Think about what a
    > floating point number looks like.
    >
    > +1.e-3
    > -.3
    > +.0e0
    > 1e-1
    > .1
    > 1


    <snip nice explanation>

    Another way that may be helpful is to produce a "railroad track" syntax
    chart (as commonly used in Pascal) for allowable representations for a
    double. I find such a method easier to follow.

    http://en.wikipedia.org/wiki/Syntax_diagram
    osmium, Oct 10, 2007
    #4
  5. osmium wrote:
    > "Gianni Mariani" writes:
    >
    >> Evyn wrote:
    >> ...
    >>> The prof. was happy, but he told me to write my own atof. So I have
    >>> converted the string to an array of char. Is this the right strategy?

    >> No need.
    >>
    >>> If so, how to I actually convert the array to a double? (As you no
    >>> doubt can see, I am pretty much in the dark here).

    >> The basis for lexical analysis is "state machine". Think about what a
    >> floating point number looks like.
    >>
    >> +1.e-3
    >> -.3
    >> +.0e0
    >> 1e-1
    >> .1
    >> 1

    >
    > <snip nice explanation>
    >
    > Another way that may be helpful is to produce a "railroad track" syntax
    > chart (as commonly used in Pascal) for allowable representations for a
    > double. I find such a method easier to follow.
    >
    > http://en.wikipedia.org/wiki/Syntax_diagram
    >
    >


    The state machine in my previous post was generated from this:

    digit = <0-9> .
    sign = <+\-> .
    opt_sign = [ sign , 0, 1 ] .
    digits = [ digit, 1, ] .
    exp = <eE> opt_sign digits .
    opt_exp = [ exp, 0, 1 ] .
    float =
    opt_sign (digits|("." digits)|(digits"."[digit,0,])) opt_exp .

    .... it's an aardvark lexical analyser syntax.
    Gianni Mariani, Oct 10, 2007
    #5
  6. Evyn

    James Kanze Guest

    On Oct 10, 3:54 pm, Gianni Mariani <> wrote:
    > Evyn wrote:


    > ...


    > > The prof. was happy, but he told me to write my own atof. So I have
    > > converted the string to an array of char. Is this the right strategy?


    > No need.


    > > If so, how to I actually convert the array to a double? (As you no
    > > doubt can see, I am pretty much in the dark here).


    > The basis for lexical analysis is "state machine". Think about what a
    > floating point number looks like.


    [Detailed explination deleted...]

    You're right, of course, but I rather suspect (or hope for him,
    at least) that this is more than what the prof wanted. And of
    course, it's only the tip of the iceberg; the real problem is
    doing the actual conversion without introducing rounding errors.
    Thus, for example, if---as seems to be the case---the only
    floating point values he'll really have to convert are of the
    form \.[0-9]+, the obvious answer is a simple loop over the
    digits:

    double value = 0.0 ;
    while ( *iter != end
    && isdigit( static_cast< unsigned char >( *iter ) ) {
    value += *iter - '0' ;
    value /= 10 ;
    }

    Except that, of course, this doesn't work in practice.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Oct 10, 2007
    #6
  7. Evyn

    Evyn Guest

    Thanks for the help and advice! Let me give it a go.
    Evyn, Oct 11, 2007
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Marco Traverso
    Replies:
    5
    Views:
    15,120
    Marco Traverso
    Dec 7, 2003
  2. Der Andere

    Double -> C-String conversion

    Der Andere, Apr 26, 2004, in forum: C++
    Replies:
    16
    Views:
    27,116
    L Russ
    Apr 27, 2004
  3. Sydex
    Replies:
    12
    Views:
    6,475
    Victor Bazarov
    Feb 17, 2005
  4. AviraM
    Replies:
    2
    Views:
    6,356
    Manish Pandit
    Sep 28, 2006
  5. J.M.
    Replies:
    5
    Views:
    778
Loading...

Share This Page