来自K& R的atof代码的说明

时间:2014-12-28 00:33:15

标签: c atof

在将字符串转换为int之前,我理解了我们在做什么,现在我们将字符串转换为double。我不明白这段代码背后的逻辑。有人可以为我澄清这一点吗?最好的问候。

#include <ctype.h>
#include <stdio.h>

//atof: convert string s to double

double atof(char s[])
{
    double val, power;
    int i, sign;

    for (i = 0; isspace(s[i]); i++) //skip whitespace
        ;
    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;
}
int main()
{
    char s[] = "78.93"; //output is 78.930000
    printf("atof equals %f\n", atof(s));
    return 0;
}

4 个答案:

答案 0 :(得分:5)

这部分非常简单,只需跳到第一个非空白字符:

for (i = 0; isspace(s[i]); i++) //skip whitespace
    ;

现在我们检查第一个非空白字符是否为 - 将其设置为负数,然后跳过字符,无论是a还是+:

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

现在开始变得棘手了。让我们使用1234.5678的示例。首先,我们要处理小数点前的部分。通过查看每个数字,将其添加到val来处理,然后如果下一个数字不是小数,则将该值乘以10直到左移它并添加下一个数字。例如,对于1234.5678,我们首先看到数字1,将其添加到val以获得1的值。下一个数字是2,所以我们多个当前的val(1)乘以10得到10然后加2得到12.下一个数字是3,所以我们将当前的val(12)乘以10得到120,然后加3得到123.下一个数字是4,所以我们将当前的val(123)乘以10得到1230,然后加4到得到1234.然后&#39;。&#39;不是数字,所以我们已经完成了数字的左侧。

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

这部分只是移过点。

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

现在我们对左边的小数右边做同样的事情,但我们也跟踪小数点后的位数(带有幂变量)。在1234.5678的示例中,我们看到的第一个数字是5.因此,我们将当前的val(1234)乘以10,并将(12345)的5加起来。我们还将功率提高到10.0。这一直持续到我们得到123456789的val和10000.0的幂。

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

最后,我们除以幂来得到正确位置的小数位(123456789 / 10000.0):

return sign * val / power;

答案 1 :(得分:2)

double atof(char s[])
{
    double val, power;
    int i, sign;

    // if there is any leading 'white space', step index past it
    // keep stepping index until other than white space encountered
    for (i = 0; isspace(s[i]); i++)
        ;

    // if there is a '-' char 
    // then indicate value is negative 
    // else assume value is positive
    // format is: result = (condition)? true value : false value
    sign = (s[i] == '-') ? -1 : 1; 

    // if there is a sign byte, step index past it
    if (s[i] == '+' || s[i] == '-')
        i++;

    // initialize the result 'val'
    // then loop through following characters
    for (val = 0.0; isdigit(s[i]); i++)
        // digits are in the range 0x30 through 0x39
        // make them integers by subtracting 0x30 ('0')
        // and update the result 'val'
        // remembering that each successive digit pushes the current result 'val'
        // to 10 times the old value then add the new 'converted' digit
        val = 10.0 * val + (s[i] - '0');
        // this ends the 'for' code block

     // when execution gets here, encountered something other than a digit
    // when a '.' encountered, step the index past it
    if (s[i] == '.')
        i++;

    // the 'power' value is indicating how much to divide the resulting
    // 'val' by to place the decimal point (if there was a decimal point)
    // into the correct position
    // if other than a digit encountered, exit loop
    for (power = 1.0; isdigit(s[i]); i++)
    {
        val = 10.0 * val + (s[i] - '0'); // see above comment about a similar line of code
        power *= 10.0;
    } // end for

    // calculate the actual value by allowing for any sign (+ or -)
    // then dividing that result by 'power' to properly place the decimal point
    return sign * val / power;
}  // end function: atof

答案 2 :(得分:1)

略过白色空间;处理一个主要标志;计算整数部分(在Val中);跳过小数;处理小数部分(通过更新Val,好像没有小数点,但也考虑到它)。

答案 3 :(得分:0)

此代码包含3个循环

第一个循环继续阅读&#39;空格&#39;直到检测到可读的东西(标志或数字)

第二个循环计算浮点左边部分的值(xxx的值在-xxx.545中)

最后一个循环使用前一个循环的值并继续右边的&#39;点&#39; 在计算数字&#39; power&#39;这是&#39;之后元素数量的10倍。 现在我们有一个浮点数左右两部分的符号和值

现在举个简单的例子:让-12.345

sign = -1
val = 12345
power = 1000 ( 10 to the power of numbers after the '.')
result is -1 * 12345 / 1000 = -12.345