ZetCode

C strtoll 函数

最后修改:2025 年 4 月 8 日

将字符串转换为数字是 C 编程中一项常见的任务,而 strtoll 是将字符串转换为长长整型的强大函数。本教程将深入介绍 strtoll,包括其语法、用法和错误处理。我们将探讨实际示例,并讨论为什么 strtollatoll 等替代方法更安全。理解 strtoll 有助于创建能够安全正确地处理数字输入的可靠程序。

什么是 strtoll?

strtoll 函数将字符串转换为长长整型。它声明在 stdlib.h 中,并提供强大的错误检查。与 atoll 不同,它可以检测转换错误并支持不同的基数。strtoll 接受三个参数:要转换的字符串、一个可选的指针用于存储结束位置,以及数字的基数。对于安全关键代码,请始终优先选择 strtoll 而非更简单但不安全的函数。

strtoll 的基本用法

此示例演示了将简单的十进制字符串转换为长长整型。

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

int main() {
    char *str = "123456789012345";
    char *endptr;
    long long num = strtoll(str, &endptr, 10);

    if (*endptr != '\0') {
        printf("Conversion stopped at: %s\n", endptr);
    } else {
        printf("Converted number: %lld\n", num);
    }

    return 0;
}

在这里,strtoll 将字符串以 10 为基数转换为长长整型。endptr 用于检测转换停止的位置。如果整个字符串都被转换,endptr 将指向空终止符。此示例显示了正确的错误检查,这与没有提供错误检测的 atoll 不同。请务必检查 endptr 来验证转换。

处理不同的基数

strtoll 可以将不同基数的数字转换为长长整型,如下所示。

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

int main() {
    char *hex_str = "0x1a3f";
    char *bin_str = "101101";
    char *oct_str = "0777";
    char *endptr;

    long long hex_num = strtoll(hex_str, &endptr, 0);
    long long bin_num = strtoll(bin_str, &endptr, 2);
    long long oct_num = strtoll(oct_str, &endptr, 8);

    printf("Hex conversion: %lld\n", hex_num);
    printf("Binary conversion: %lld\n", bin_num);
    printf("Octal conversion: %lld\n", oct_num);

    return 0;
}

此示例展示了不同基数的转换。基数 0 允许自动检测十六进制(0x 前缀)、八进制(0 前缀)或十进制。显式基数(2 用于二进制,8 用于八进制)会强制以该基数进行解释。该函数会跳过前导空格,并在遇到第一个无效字符时停止。这种灵活性使得 strtoll 对于各种输入格式都非常通用。

使用 strtoll 进行错误处理

此示例演示了使用 strtoll 进行全面的错误处理。

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

int main() {
    char *str = "999999999999999999999999";
    char *endptr;
    errno = 0;
    
    long long num = strtoll(str, &endptr, 10);

    if (errno == ERANGE) {
        printf("Range error: ");
        if (num == LLONG_MAX) printf("Overflow\n");
        else if (num == LLONG_MIN) printf("Underflow\n");
    } else if (*endptr != '\0') {
        printf("Partial conversion: stopped at '%s'\n", endptr);
    } else {
        printf("Successful conversion: %lld\n", num);
    }

    return 0;
}

此代码展示了 strtoll 的正确错误处理。我们检查 errno 以处理范围错误(ERANGE),并检查返回值以处理溢出/下溢。endptr 用于检测部分转换。在调用 strtoll 之前,请务必将 errno 设置为 0,以区分当前错误和之前的错误。这种方法提供了比简单函数更全面的错误检测。

将 strtoll 用于用户输入

此示例展示了使用 strtoll 安全地处理用户输入。

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

int main() {
    char input[100];
    printf("Enter a number: ");
    fgets(input, sizeof(input), stdin);

    char *endptr;
    errno = 0;
    long long num = strtoll(input, &endptr, 10);

    if (endptr == input) {
        printf("Error: No digits found\n");
    } else if (*endptr != '\n' && *endptr != '\0') {
        printf("Error: Invalid characters in input\n");
    } else if (errno == ERANGE) {
        printf("Error: Number out of range\n");
    } else {
        printf("You entered: %lld\n", num);
    }

    return 0;
}

在这里,fgets 安全地读取用户输入,而 strtoll 则进行完整的错误检查进行转换。我们验证是否转换了任何数字(endptr == input),检查是否有尾随字符,并处理范围错误。这种方法可以防止因无效输入而导致的程序崩溃,并提供清晰的错误消息。处理用户提供的数字时,请始终使用此模式。

strtoll 的高级功能

此示例演示了本地化感知转换和高级解析。

advanced_features.c
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

int main() {
    setlocale(LC_NUMERIC, "de_DE.UTF-8"); // German locale uses ',' as decimal
    char *str = "1.234.567"; // German thousand separators
    char *endptr;

    long long num = strtoll(str, &endptr, 10);

    if (*endptr != '\0') {
        printf("Stopped at: '%s'\n", endptr);
        printf("Converted part: %lld\n", num);
    } else {
        printf("Full conversion: %lld\n", num);
    }

    return 0;
}

此示例展示了本地化设置如何影响 strtoll。在德语本地化中,句点是千位分隔符,而不是小数点。该函数在遇到第一个非数字字符时停止,但会返回已转换的部分。请注意,strtoll 仅处理整数部分 - 对于浮点数,请使用 strtod。这演示了 strtoll 在处理本地化数字格式时的行为。

使用 strtoll 的最佳实践

来源

C strtoll 文档

本教程介绍了 strtoll 函数,从基本用法到高级功能。正确使用 strtoll 可以创建健壮的程序,通过全面的错误检测安全地处理数字输入转换。

作者

我叫 Jan Bodnar,是一名敬业的程序员,对编码充满热情。自 2007 年以来,我通过 1400 多篇文章和 8 本电子书分享我的专业知识。凭借十多年的教学经验,我致力于让编程变得触手可及且引人入胜。

列表 C 标准库