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
版权声明:本文为eye_water原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/eye_water/article/details/80627349

智能推荐

C语言main函数参数详解

main函数参数 一共有三个: 1.int argc 整型变量 2.char *argv[] 字符指针的数组,通俗一点就是字符串数组,每个元素都是字符串 3.char *envp[] 字符串数组 这三个东西再怎么神秘,也只是函数参数,只不过是main函数的参数罢了!   一、int argc参数 用于存放命令行参数的个数 二、char *argv[]参数 每个元素都是一个字符串,表示命令...

微生物生态:从phyloseq对象输出β多样性箱线图

微生物生态:从phyloseq对象输出β多样性箱线图 有些时候,β多样性的比较都是用排序的方法实现,但也可以换换口味,用箱线图比较,比如这样: 这时候,需要利用Bray-Curtis,或者其他类型的距离矩阵,分组统计。如果你的距离矩阵包含在phyloseq里,那么下面的代码会帮你把phyloseq对象,转换为可以做箱线图的格式。 作图:...

自己做一个table插件 (一)Ajax获取数据后动态生成table

    今天我给大家带来一个简单的JQ插件,Ajax获取数据后动态生成table。当然,有这种功能的插件有很多。著名的有DataTable、JqGrid……它们虽然功能丰富,成熟,拿来做二次开发是一个不错的选择。但是,我仍然自己写了一个插件,原因很简单,它们太庞大了,它的百分之九十的功能我都用不上。    &n...

脚本实现Unity 场景的淡入淡出

看到一个场景淡入淡出的脚本文件,分享一下,原文章见来源   操作如下: 1.创建一个Shader文件   2.双击打开该Shader文件,输入如下代码,更改Shader:   3.创建一个C#脚本文件,代码如下:       4.将C#脚本挂载到摄像机上,运行如下(左键点击Game场景)   以上为全部详细讲解...

【CSS】526- CSS 控制图标颜色

原文地址:http://eux.baidu.com/blog/fe/控制图标颜色 背景 实际项目中,一般都会遇到不同颜色的图标,例如   导航栏图标的不同状态 方法 方法1 需要UI设计师给出不同颜色的图标,在不同状态下设置不同的元素背景。 缺点是:当状态改变后,浏览器才去拉取active状态的图片,所以视觉上会有闪动,体验不好 方法2 将两张图标合成雪碧图 优点:解决第一个方法闪动的问...

猜你喜欢

双链表

双链表的初始化(带头结点) 双链表在单链表的结点中增加了一个指向其前驱的prior指针,因此在双链表中执行按值查找和按位查找的操作与单链表一样,但在删除和插入结点中双链表时间复杂度O(1),单链表为O(n)。 双链表的插入 双链表的删除 双链表的遍历...

洛谷4363 [九省联考2018]一双木棋chess

标签:状压,记忆化搜索 题目 题目传送门 题目描述 菲菲和牛牛在一块n 行m 列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手。 棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落子,直到填满棋盘时结束。 落子的规则是:一个格子可以落子当且仅当这个格子内没有棋子且这个格子的左侧及上方的所有格子内都有棋子。 棋盘的每个格子上,都写有两个非负整数,从上到下第i 行中从左到右第j 列的格 子上的两个整数记...

忘掉什么鬼并发,先听完这个故事!

点击上方“阿拉奇学Java”,选择“置顶或者星标” 优质文章第一时间送达! 来源 | cnblogs.com/flashsun/p/11017431.html 推荐阅读 | SQL语句大全,所有的SQL都在这里(建议收藏) 最近在给别人讲解Java并发编程面试考点时,为了解释锁对象这个概念,想了一个形象的故事。后来慢慢发现这个故事似乎能讲解...

10-数据存储

数据存储 内容 列表 元组 集合 字典 公共函数 切片 推导式 1. 列表 1.1 列表的概念 列表是一种存储大量数据的存储模型。 1.2 列表的特点 列表具有索引的概念,可以通过索引操作列表中的数据。列表中的数据可以进行添加、删除、修改、查询等操作。 1.3 列表的基本语法 创建列表: 变量名 = [数据1,数据2,……] 获取列表数据: 变量名[索引] 修改列表数据...

android studio中的(PercentFrameLayout)百分比布局

在《第一行代码》中,原先按照书中内容配置,无法正常运行,记录一下解决过程。 书中步骤如下: 在/app/build.gradle中添加依赖 之后在activity_main.xml中进行布局 运行程序,发现模拟器上android程序卡死。 解决过程: 在网上搜索了解决方法,大多都是修改版本,我运行起来依然无效。在查阅文档资料后(支持库工键映射),发现 com.android.support:per...