C语言strtol 函数使用方法

发布于:2025-09-09 ⋅ 阅读:(21) ⋅ 点赞:(0)

C语言中 strtol 函数的具体使用方法:

1. 函数原型

#include <stdlib.h> // 必需的头文件

long int strtol(const char *str, char **endptr, int base);

2. 功能描述

strtol 函数将 str 所指向的字符串根据给定的 base(基数,2-36)转换为一个 long int 类型的长整数。

它会跳过字符串开头的所有空白字符(空格、换行符、制表符等),然后读取尽可能多的字符来组成一个合法的整数表示,最后将后续无法转换的部分的指针存储在 endptr 所指向的位置。

3. 参数详解

  1. const char *str

    • 这是指向要转换的以空字符(\0)结尾的字符串的指针。

  2. char **endptr

    • 这是一个指向字符指针的指针。函数会将转换过程中第一个无效字符的地址存入 *endptr

    • 如果 endptr 不是 NULL,你可以通过检查这个值来判断转换在何处停止。

    • 如果整个字符串都无法转换(例如,开头就是非数字字符),str 的值会被赋给 *endptr

    • 如果你不关心转换停止的位置,可以将此参数设置为 NULL

  3. int base

    • 这是转换的基数(即进制),范围必须是 2 到 36

    • 特殊值 0:如果 base 为 0,函数会自动检测数字的进制:

      • 如果字符串以 0x 或 0X 开头,则按十六进制(16)解释。

      • 如果字符串以 0 开头,则按八进制(8)解释。

      • 否则,按十进制(10)解释。

4. 返回值

  • 成功时:返回转换后的 long int 值。

  • 失败时

    • 如果无法进行任何转换(如字符串为空或格式错误),返回 0

    • 如果转换结果超出 long int 可表示的范围,则返回 LONG_MAX 或 LONG_MIN(定义在 <limits.h> 中),并设置全局变量 errno 为 ERANGE(表示范围错误)。


5. 使用示例与场景分析

示例 1:基本转换(不关心结束位置)
#include <stdio.h>
#include <stdlib.h>

int main() {
    const char *str1 = "12345Hello";
    const char *str2 = "   -6789";
    const char *str3 = "0x2A"; // 十六进制的 42

    long int num1 = strtol(str1, NULL, 10);
    long int num2 = strtol(str2, NULL, 10);
    long int num3 = strtol(str3, NULL, 0); // 使用基数 0 自动检测

    printf("'%s' -> %ld\n", str1, num1); // 输出:'12345Hello' -> 12345
    printf("'%s' -> %ld\n", str2, num2); // 输出:'   -6789' -> -6789
    printf("'%s' -> %ld\n", str3, num3); // 输出:'0x2A' -> 42

    return 0;
}
示例 2:使用 endptr 处理后续字符

这个例子展示了如何利用 endptr 来处理字符串中混合了数字和非数字的情况,例如解析 "100 cats"

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

int main() {
    const char *str = "100 cats and 2 dogs";
    char *endptr;
    long int num;

    num = strtol(str, &endptr, 10); // 注意:这里传递的是 endptr 的地址

    printf("Original string: \"%s\"\n", str);
    printf("Converted number: %ld\n", num);   // 输出:100
    printf("The rest of the string: \"%s\"\n", endptr); // 输出: cats and 2 dogs

    // 可以继续用 endptr 作为新的起点进行下一次转换
    str = endptr; // 跳过已转换的部分
    num = strtol(str, &endptr, 10);
    printf("Next number: %ld\n", num);       // 输出:0,因为" cats"不是数字开头
    printf("The rest now: \"%s\"\n", endptr); // 输出: cats and 2 dogs

    return 0;
}
示例 3:错误处理

这是一个健壮性更强的例子,演示了如何处理转换错误和溢出。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>   // 用于 errno
#include <limits.h>  // 用于 LONG_MAX, LONG_MIN

void test_conversion(const char *str, int base) {
    char *endptr;
    long int num;

    // 在进行新转换前,先将 errno 重置为 0
    errno = 0;

    num = strtol(str, &endptr, base);

    // 检查转换是否失败
    if (str == endptr) {
        printf("错误:字符串 '%s' 中没有任何数字。\n", str);
    }
    // 检查是否发生溢出
    else if (errno == ERANGE) {
        if (num == LONG_MAX) {
            printf("错误:字符串 '%s' 转换结果上溢(超过 LONG_MAX)。\n", str);
        } else if (num == LONG_MIN) {
            printf("错误:字符串 '%s' 转换结果下溢(低于 LONG_MIN)。\n", str);
        }
    }
    // 检查是否成功转换了整个数字部分
    else if (*endptr != '\0') {
        printf("警告:成功转换了部分内容 '%ld',但后续有非数字字符:'%s'\n", num, endptr);
    }
    // 完全成功的转换
    else {
        printf("成功:字符串 '%s' 被转换为 %ld\n", str, num);
    }
}

int main() {
    test_conversion("9999999999999999999999", 10); // 一个非常大的数
    test_conversion("-9999999999999999999999", 10); // 一个非常小的数
    test_conversion("123abc", 10);
    test_conversion("abc123", 10);

    return 0;
}

可能的输出:

错误:字符串 '9999999999999999999999' 转换结果上溢(超过 LONG_MAX)。
错误:字符串 '-9999999999999999999999' 转换结果下溢(低于 LONG_MIN)。
警告:成功转换了部分内容 '123',但后续有非数字字符:'abc'
错误:字符串 'abc123' 中没有任何数字。

6. 重要注意事项

  1. endptr 的使用endptr 是一个二级指针,传递参数时需要使用 & 操作符(例如 &my_endptr)。

  2. 空白字符:函数会自动跳过开头的空白字符。

  3. 正负号:函数能够识别字符串开头的 + 或 - 号。

  4. 基数与字符集

    • 对于基数 11 到 36,字母 a-z(或 A-Z)被用来表示数字 10 到 35。转换是不区分大小写的。

    • 确保你提供的 base 参数对于你要转换的数字是合理的。例如,用 base=2 去转换 "12" 会得到 1(因为 '2' 在二进制中是非法字符,转换在 '2' 前停止)。

  5. 错误检查:始终检查 errno 和 endptr 来确保转换成功且没有溢出,这是编写健壮程序的关键。

总结

场景 检查方法
完全成功 *endptr == '\0' 且 errno != ERANGE
部分成功 *endptr != '\0' 且 errno != ERANGE
无数字可转 endptr == str (传入的字符串指针)
数值溢出 errno == ERANGE,且返回值为 LONG_MAX 或 LONG_MIN

熟练掌握 strtol 是处理字符串到整数转换的最佳实践,它比古老的 atoi 函数更安全、更强大。


网站公告

今日签到

点亮在社区的每一天
去签到