ZetCode

C strtod 函数

最后修改:2025 年 4 月 8 日

字符串到数字的转换是 C 编程中的一项常见任务,而 strtod 是将字符串转换为双精度浮点值的标准函数。本教程将深入介绍 strtod,包括其语法、用法和错误处理。我们将探讨实际示例,并讨论为什么 strtodatof 等替代方法更安全。理解正确的字符串转换有助于防止程序中的错误和安全漏洞。

什么是 strtod?

strtod 函数将字符串转换为双精度浮点值。它在 stdlib.h 中声明,并接受两个参数:要转换的字符串和一个可选指针,用于存储转换的结束位置。strtod 提供强大的错误处理并检测无效输入,而 atof 则不提供任何错误检测。对于安全关键代码,请始终优先使用 strtod 而不是更简单但不安全的替代方法。

strtod 的基本用法

此示例演示了使用 strtod 进行基本的字符串到双精度浮点数的转换。

basic_conversion.c
#include <stdio.h>
#include <stdlib.h>

int main() {
    const char *str = "3.14159";
    char *endptr;
    double value = strtod(str, &endptr);

    if (str == endptr) {
        printf("No conversion performed\n");
    } else {
        printf("Converted value: %f\n", value);
        printf("Remaining string: \"%s\"\n", endptr);
    }

    return 0;
}

在这里,strtod 将字符串 "3.14159" 转换为双精度浮点值。endptr 指向未转换的第一个字符。这允许检查转换是否成功以及字符串的哪个部分被处理。始终检查 endptr 以验证转换是否成功。该函数会自动处理前导空格。

使用 strtod 进行错误处理

此示例显示了如何检测和处理转换错误。

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

int main() {
    const char *str = "123.45abc";
    char *endptr;
    errno = 0;
    double value = strtod(str, &endptr);

    if (str == endptr) {
        printf("No digits found\n");
    } else if (errno == ERANGE) {
        printf("Value out of range\n");
    } else {
        printf("Converted value: %f\n", value);
        printf("Stopped at: '%s'\n", endptr);
    }

    return 0;
}

此代码演示了对 strtod 进行全面的错误检查。我们检查 errno 是否有范围错误,并比较 strendptr 以检测无转换情况。该示例还显示了 strtod 如何在遇到第一个无效字符时停止。始终在调用 strtod 之前重置 errno 以进行可靠的错误检测。

转换不同的数字格式

strtod 可处理各种数字格式,如下面的示例所示。

number_formats.c
#include <stdio.h>
#include <stdlib.h>

int main() {
    const char *examples[] = {
        "42", "-3.14", "1.23e4", "0x1.8p1", "inf", "NAN"
    };
    
    for (int i = 0; i < 6; i++) {
        char *endptr;
        double value = strtod(examples[i], &endptr);
        
        printf("String: \"%s\"\n", examples[i]);
        printf("Converted to: %f\n\n", value);
    }

    return 0;
}

此示例展示了 strtod 如何转换不同的数字格式:整数、负数、科学计数法、十六进制浮点数、无穷大和 NaN。该函数处理所有这些标准的 C 浮点数表示。请注意,十六进制浮点数和无穷大等特殊值需要 C99 或更高版本。小数点转换是区域设置无关的。

安全替代方案:strtod 结合完整验证

此示例演示了使用 strtod 进行完整的输入验证。

full_validation.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>

int validate_double(const char *str, double *result) {
    char *endptr;
    errno = 0;
    *result = strtod(str, &endptr);
    
    if (str == endptr) return 0; // No conversion
    if (errno == ERANGE) return 0; // Out of range
    
    // Skip whitespace after number
    while (isspace((unsigned char)*endptr)) endptr++;
    
    return *endptr == '\0'; // Valid if reached end of string
}

int main() {
    const char *input = "  123.45  ";
    double value;
    
    if (validate_double(input, &value)) {
        printf("Valid number: %f\n", value);
    } else {
        printf("Invalid number format\n");
    }

    return 0;
}

此健壮的验证函数使用 strtod 检查完整的数字转换。它处理前导/尾随空格、范围错误,并确保消耗了整个字符串。该函数在输入有效数字时返回 1,在输入无效时返回 0。当处理不受信任的输入或用户提供的数据时,推荐使用此方法。它比不提供错误检测的 atof 更安全。

从字符串解析多个数字

此示例显示了如何使用 strtod 从字符串中提取多个数字。

multiple_numbers.c
#include <stdio.h>
#include <stdlib.h>

int main() {
    const char *data = "12.5, 7.8, 3.14, 9.99";
    const char *ptr = data;
    char *endptr;
    
    while (*ptr != '\0') {
        double value = strtod(ptr, &endptr);
        
        if (ptr == endptr) break; // No conversion
        
        printf("Found number: %f\n", value);
        
        // Move past the number and any separators
        ptr = endptr;
        while (*ptr == ',' || isspace(*ptr)) ptr++;
    }

    return 0;
}

在这里,strtod 在循环中使用,以从逗号分隔的字符串中提取所有数字。每次转换后,endptr 用于在字符串中前进。此技术可用于解析包含多个值的配置文件或用户输入。代码会跳过数字之间的逗号和空格。始终检查 ptr 是否已前进以检测转换失败。

使用 strtod 的最佳实践

来源

C strtod 文档

本教程探讨了 strtod 函数,从基本用法到高级验证技术。正确的字符串到数字转换对于健壮、安全的 C 程序至关重要。当输入验证很重要时,请始终优先使用 strtod 而不是更简单的替代方法。

作者

我的名字是 Jan Bodnar,我是一名敬业的程序员,对编码充满热情。自 2007 年以来,我通过 1,400 多篇文章和 8 本电子书分享我的专业知识。拥有十多年的教学经验,我努力使编程变得易于理解和引人入胜。

列表 C 标准库