Help | Site Map
Connecting Tech Pros Worldwide
 
 
LinkBack Thread Tools
  #1  
Old July 23rd, 2005, 03:02 AM
JS
Guest
 
Posts: n/a
Default I don't understand this code.

#include <ctype.h>
double atof(char s[]){

double val, power;
int i, sign;

for (i = 0; isspace(s[i]); i++)
;
sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '+' || s[i] == '-')
i++;

for (val = 0.0; isdigit(s[i]); i++)
val = 10.0 * val + (s[i] - '0');

if (s[i] == '.')
i++;

for (power = 1.0; isdigit(s[i]); i++){
val = 10.0 * val + (s[i] - '0');
power *= 10.0;
}
return sign * val / power;
}



The first for loop never terminates and I guess nothing is executed in its
body.

How should (s[i] - '0') be understood? Have never seen a char subtracted
from another char before.



JS



  #2  
Old July 23rd, 2005, 03:02 AM
Larry Brasfield
Guest
 
Posts: n/a
Default Re: I don't understand this code.

"JS" <sfsdfs@asdas.com> wrote in message
news:d14m9k$gmd$1@news.net.uni-c.dk...[color=blue]
> #include <ctype.h>
> double atof(char s[]){
>
> double val, power;
> int i, sign;
>
> for (i = 0; isspace(s[i]); i++)
> ;
> sign = (s[i] == '-') ? -1 : 1;
> if (s[i] == '+' || s[i] == '-')
> i++;
>
> for (val = 0.0; isdigit(s[i]); i++)
> val = 10.0 * val + (s[i] - '0');
>
> if (s[i] == '.')
> i++;
>
> for (power = 1.0; isdigit(s[i]); i++){
> val = 10.0 * val + (s[i] - '0');
> power *= 10.0;
> }
> return sign * val / power;
> }
>
>
>
> The first for loop never terminates and I guess nothing is executed in its
> body.[/color]

It looks to me as if it should terminate in
some fashion, either by finding a non-space
or producing an address fault. (I assume
that the data memory is not all whitespace.)

Your interpretation of the empty statement
is correct.
[color=blue]
> How should (s[i] - '0') be understood? Have never seen a char subtracted
> from another char before.[/color]

That is the usual way of converting a sequential
set of numeral character codes into their numeric
equivalents. '0' maps to 0, ..., '9' maps to 9.

--
--Larry Brasfield
email: donotspam_larry_brasfield@hotmail.com
Above views may belong only to me.


  #3  
Old July 23rd, 2005, 03:02 AM
Howard
Guest
 
Posts: n/a
Default Re: I don't understand this code.


"JS" <sfsdfs@asdas.com> wrote in message
news:d14m9k$gmd$1@news.net.uni-c.dk...[color=blue]
> #include <ctype.h>
> double atof(char s[]){
>
> double val, power;
> int i, sign;
>
> for (i = 0; isspace(s[i]); i++)
> ;
> sign = (s[i] == '-') ? -1 : 1;
> if (s[i] == '+' || s[i] == '-')
> i++;
>
> for (val = 0.0; isdigit(s[i]); i++)
> val = 10.0 * val + (s[i] - '0');
>
> if (s[i] == '.')
> i++;
>
> for (power = 1.0; isdigit(s[i]); i++){
> val = 10.0 * val + (s[i] - '0');
> power *= 10.0;
> }
> return sign * val / power;
> }
>
>
>
> The first for loop never terminates and I guess nothing is executed in its
> body.
>[/color]

That loop moves the starting point of the parsing code up past any leading
spaces. There is not protection there if the array passed contains only
spaces and no null terminator at the end, so I assume it's a requirement
that the function be provided a valid null-terminated string. If it never
terminates, then you've given it invalid data.
[color=blue]
> How should (s[i] - '0') be understood? Have never seen a char subtracted
> from another char before.[/color]

That's a common method if getting the values 0 through 9 from the characters
'0' through '9'. It only works if your character set contains the
characters '0' through '9' in order (which they all do, from everything I've
seen, but I don't know if it's a requirement). If you subtract '0' from '0,
you get 0. If you subtract '0' from '3', you get 3. Etc.

The code is taking a string containing a representation of a floating-point
number, and converting into an actual float value.

-Howard



  #4  
Old July 23rd, 2005, 03:02 AM
evaned@gmail.com
Guest
 
Posts: n/a
Default Re: I don't understand this code.

There are a couple common idioms in the code you cite, and you have a
question about each of them. Let's look at them in turn:
[color=blue]
> for (i = 0; isspace(s[i]); i++) ;[/color]

This "fast forwards" over spaces at the beginning of the number. This
way the function will still work for things like " 1.234". The later
parts expect the index i to be loooking at a number, so this puts it at
the beginning.

Remember that the expressions inside a for loop can have side effects.
In this case, the index i is changing. I'll rewrite the for loop as a
while loop that might be a little more clear:

i = 0
while( isspace(s[i]) )
i++;

So what this does is, starting with the beginning of the string,
increment the index i until s[i] is not a space.

[color=blue]
> How should (s[i] - '0') be understood? Have never seen a char[/color]
subtracted
from another char before.

This is by far the most common way to convert a digit storted in a
character (e.g. the character '4', as opposed to the character with
ASCII code 4) to a number. In ASCII and probably most other character
sets (though not all, so this isn't strictly portable), all the digits
are together and in order. For instance, I'm pretty sure '0' has ASCII
code 48. If so, '1' has ASCII code 49, '2' has ASCII code 50, etc. (If
you're wondering, 48 is 30 hex, so the digits are from 30 to 39 hex.
Letters start at 41 and 61 hex, or 65 and 97 dec.)

When you subtract two characters you get the difference in their ASCII
values. For instance, '2' - '1' translates to 49 - 48, which is 1.
You'll notice because of the numbers' placement, all the subtractions
work out "right". '9' - '4' is indeed 5 for example. (Note too that
that is the integer 5, not '5'.) And so any digit minus '0' is that
digit as an integer.

In the atof function, s[i] holds a digit that needs to be converted to
an integer so that something sane can be done with it.

A quick run through of the for loop on lines 13-14 might be as follows:
(this part of the function is converting everything to the left of the
decimal place to a number; indeed, if you were to look at the function
atoi, you would probably see the same code up to that point except with
val as an int instead of a double)

- The string s contains "135", val starts out as 0 (the first
expression in the for loop), and i starts as 0 (the for loop explained
above doesn't iterate at all; the expression is false right from the
start so i++ is never run)
- The first iteration, val is multiplied by 10 to get 0, then to that
is added s[i] - '0' = s[0] - '0' = '1' - '0' = 1, so val = 1 after the
first iteration
- The second iteration, val is multiplied by 10 to get 10, then to that
is added s[i] - '0' = s[1] - '0' = '2' - '0' = 1, so val = 10+2 = 12
after the second iteration
- The third iteration, val is multiplied by 10 to get 120, then to that
is added s[i] - '0' = s[2] - '0' = '3' - '0' = 1, so val = 120+3 = 123
after the third iteration
- At this point, i = 4 and s[4] = '\0' (the null character that marks
the end of every C string), so isdigit(s[i]) is false and the loop
terminates.

Does the function make more sense now?

  #5  
Old July 23rd, 2005, 03:02 AM
Pete Becker
Guest
 
Posts: n/a
Default Re: I don't understand this code.

evaned@gmail.com wrote:[color=blue]
> In ASCII and probably most other character
> sets (though not all, so this isn't strictly portable), all the digits
> are together and in order.[/color]

That's required, in both C and C++.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
  #6  
Old July 23rd, 2005, 03:02 AM
JS
Guest
 
Posts: n/a
Default Re: I don't understand this code.

Thanks to all three of you for a very clarifying explanation!

JS


  #7  
Old July 23rd, 2005, 03:02 AM
evaned@gmail.com
Guest
 
Posts: n/a
Default Re: I don't understand this code.

Oh, I didn't know that. Thanks! You learn something every day! That's
part of why I read these boards... ;-)

  #8  
Old July 23rd, 2005, 03:03 AM
Richard Cavell
Guest
 
Posts: n/a
Default Re: I don't understand this code.

On 15/3/05 5:55 AM, JS wrote:[color=blue]
> #include <ctype.h>
> double atof(char s[]){
>
> double val, power;
> int i, sign;
>
> for (i = 0; isspace(s[i]); i++)
> ;
> sign = (s[i] == '-') ? -1 : 1;
> if (s[i] == '+' || s[i] == '-')
> i++;
>
> for (val = 0.0; isdigit(s[i]); i++)
> val = 10.0 * val + (s[i] - '0');
>
> if (s[i] == '.')
> i++;
>
> for (power = 1.0; isdigit(s[i]); i++){
> val = 10.0 * val + (s[i] - '0');
> power *= 10.0;
> }
> return sign * val / power;
> }
>
>
>
> The first for loop never terminates and I guess nothing is executed in its
> body.[/color]

It has the function of incrementing i to be an offset to the first
non-whitespace character.
[color=blue]
> How should (s[i] - '0') be understood? Have never seen a char subtracted
> from another char before.[/color]

Characters are represented by numbers, so that the character '0'
translates into a particular number. In most if not all character sets,
the characters that represent numbers are sequential. So whatever
number '0' translates into, plus 1, will translate back into '1' and so on.
  #9  
Old July 23rd, 2005, 03:07 AM
Sven Heyll
Guest
 
Posts: n/a
Default Re: I don't understand this code.

Let me comment on the code:
[color=blue]
> #include <ctype.h>
> double atof(char s[]){
>
> double val, power;
> int i, sign;
>[/color]

Eat whitespaces...[color=blue]
> for (i = 0; isspace(s[i]); i++)
> ;[/color]

Is the first char a "-"? in that case set sign to -1
if it is a '+' not a minus do nothing but in either case: eat the char
(+ or -)...[color=blue]
> sign = (s[i] == '-') ? -1 : 1;
> if (s[i] == '+' || s[i] == '-')
> i++;[/color]

Start processing the digits until a non digit char occures.
During process the current digit is found by substracing the charachter
code wich symbolizes the 0, and is added to the variable that
accumulates all digits. Of course this variable must be multiplied by 10
before the digit is added, we are decimal format...[color=blue]
> for (val = 0.0; isdigit(s[i]); i++)
> val = 10.0 * val + (s[i] - '0');[/color]

Ok all digits eaten.

Now check for a '.' if there is one an exponent is expected. The '.'
char is eaten of course.[color=blue]
> if (s[i] == '.')
> i++;
>[/color]

Why does the following work? Very simple:
There are three actually two possibilities:
either the string contained
a '.'
a number
or something else
IT COULD NOT have contained a number as all numbers were eaten.
That leaves two possibilities to consider:
there was a '.' char(1)
there was something else (2)
Only a '.' char would have been eaten(case 1) not any other(necessaryly
non-digit) char(case 2).
It follows directly that the next character is a digit ONLY if a '.'
char was eaten above.

So the following loop can safely rely on that, and it also does so by
(blindly) running as long as the current character is a digit.

It accumulates the digits into the variable val in the same fashion as
the first digit eating loop does. It also multiplies another
variable(power) by 10 each loop, in order to be able to take the digits
position after decimal point into account.[color=blue]
> for (power = 1.0; isdigit(s[i]); i++){
> val = 10.0 * val + (s[i] - '0');
> power *= 10.0;
> }[/color]

The parts arer composed and returned...[color=blue]
> return sign * val / power;
> }
>
>
>
> The first for loop never terminates and I guess nothing is executed in its[/color]
false[color=blue]
> body.[/color]
false also!! i++ belongs the the "body" i++ means "eat a
character!" (in this case whitespace characters)[color=blue]
>
> How should (s[i] - '0') be understood? Have never seen a char subtracted
> from another char before.[/color]
numbers are represented as a dense sequence in the character symbol
table. To get 1 from a char containing '1' we can therefor substract
the symbol table index of '1' from the index at '0':

char cx = '1';
int x = cx - '0';

Hope I could ghelp you.

Greetings,
Sven Heyll
 

Bookmarks

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are Off
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

What is Bytes?

We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights. Get the best answers to your questions from over network members.
Post your question now . . .
It's fast and it's free

Popular Articles