1. 程式人生 > >c語言strtod()函式詳解

c語言strtod()函式詳解

前言

網上有很多關於strtod()函式的文章,不過大部分都是用strtod()函式轉換一個字元

char *str = "111.11";
char *target;
double ret;
ret = strtod(str, &target);

很少有轉換字串的這樣的用法

char *p = "111.11 -2.22 Nan nan(2) inF 0X1.BC70A3D70A3D7P+6  1.18973e+4932zzz";

本文主要參考strtod()函式, 只是對其中的程式碼示例進行解釋,當然我理解示例程式碼時遇到了一點問題,在StackOverflow提問了以下,結果Barmar大神直接把程式碼解釋了一遍,很佩服這位大神,

StackOverflow版連結

程式碼分析

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>

int main(void)
{
    // parsing with error handling
    const char *p = "111.11 -2.22 Nan nan(2) inF 0X1.BC70A3D70A3D7P+6  1.18973e+4932zzz";
    printf("Parsing '%s':\n", p);
    char *end;
    for (double
f = strtod(p, &end); p != end; f = strtod(p, &end)) { printf("'%.*s' -> ", (int)(end-p), p); p = end; if (errno == ERANGE){ printf("range error, got "); errno = 0; } printf("%f\n", f); } // parsing without error handling
printf("\" -0.0000000123junk\" --> %g\n", strtod(" -0.0000000123junk", NULL)); printf("\"junk\" --> %g\n", strtod("junk", NULL)); }

問題 1:

p = end //這條語句是幹什麼用的?

strtod()函式的引數:

double      strtod( const char          *str, char          **str_end );

str 指向字串的指標
end_str 指向指標的指標
在未呼叫strtod()函式前,列印字串指標p以及end的地址

printf("%p\n", p);
printf("%p\n", end); 

執行結果

0000000000408000
000000000000002D

接下來在執行迴圈時,列印pend的地址

for (f = strtod(p, &end); p != end; f = strtod(p, &end))
     {
        printf("p addr = %p\n", p);
        printf("end addr = %p\n", end);
        printf("'%.*s' -> ", (int)(end-p), p);
        p = end;
        if (errno == ERANGE){
            printf("range error, got ");
            errno = 0;
        }
        //printf("%f\n", f);
    }

輸出

p addr = 0000000000408000
end addr = 0000000000408006
'111.11' -> 111.110000
p addr = 0000000000408006
end addr = 000000000040800C
' -2.22' -> -2.220000
p addr = 000000000040800C
end addr = 0000000000408010
' Nan' -> 1.#QNAN0
p addr = 0000000000408010
end addr = 0000000000408017
' nan(2)' -> 1.#SNAN0
p addr = 0000000000408017
end addr = 000000000040801B
' inF' -> 1.#INF00
p addr = 000000000040801B
end addr = 0000000000408030
' 0X1.BC70A3D70A3D7P+6' -> 111.110000
p addr = 0000000000408030
end addr = 000000000040803F

可以發現end指標總會指向當前字串中某一個字元的下一個字元,p指標會指向當前字串中某一個字元
這裡寫圖片描述
因此p = end這條語句實現了對字串中的所有字元進行strtod()操作,而當for (f = strtod(p, &end); p != end; f = strtod(p, &end))語句中的p = end時,也即是沒有字元需要進行strtod()操作了,就可以退出迴圈

問題2:

printf("'%.*s' -> ", (int)(end-p), p);

打印出的為什麼是一系列字元,如:

'111.11'
' -2.22'
' Nan'
' nan(2)'
' inF'
' 0X1.BC70A3D70A3D7P+6'
'  1.18973e+4932'

(int)(end - p)計算長度, %.*s中的*代表長度,也即是從當前字串中選取多少個字元進行列印
示例程式碼:

#include<stdio.h>

int main ()
{
    char *p = "Hello World!";
    printf("length = 2 str = %.2s\n", p);
    printf("length = 3 str = %.3s\n", p);
}

輸出

length = 2 str = He
length = 3 str = Hel