3

我明白我们在做什么,在我们将字符串转换为 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

4 回答 4

6

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

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

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

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

现在它开始变得棘手。让我们以 1234.5678 为例。首先我们要处理小数点前的部分。它通过查看每个数字来处理,将其添加到 val,然后如果下一个数字不是小数,则将 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。然后是 '.' 不是数字,所以我们已经完成了数字的左侧。

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;
于 2014-12-28T00:49:53.153 回答
3
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
于 2014-12-28T06:27:23.680 回答
1

跳过空白;处理一个领先的标志;计算整数部分(以 Val 为单位);跳过小数点;处理小数部分(通过更新 Val 就好像没有小数点一样,但也可以考虑它)。

于 2014-12-28T00:42:46.617 回答
0

此代码由 3 个循环组成

第一个循环继续读取“空格”,直到检测到可读的内容(符号或数字)

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

最后一个循环使用前一个循环的值并继续“点”的右侧部分,同时计算数字“幂”,即“。”之后元素数量的 10 次方。现在我们有了浮点数左右部分的符号和值

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

sign = -1
val = 12345
power = 1000 ( 10 to the power of numbers after the '.')
result is -1 * 12345 / 1000 = -12.345
于 2014-12-28T00:47:37.017 回答