C strtol 函数
最后修改:2025 年 4 月 8 日
字符串到数字的转换是 C 编程中的一项常见任务,而 strtol 是一个功能强大的函数。本教程将深入介绍 strtol,包括其语法、用法和错误处理。我们将探讨为什么 strtol 比 atoi 等函数更安全,并提供实际示例。理解 strtol 有助于在处理字符串中的数字输入时编写更可靠的代码。
什么是 strtol?
strtol 函数将字符串转换为长整数。它在 stdlib.h 中声明,并提供强大的错误检查。与 atoi 不同,strtol 可以检测转换错误并支持不同的数字基数。它接受三个参数:要转换的字符串、一个用于存储结束位置的可选指针以及数字基数。为了可靠地进行字符串转换,请始终优先选择 strtol 而不是 atoi。
strtol 的基本用法
此示例演示了使用 strtol 进行基本的字符串到长整数的转换。
#include <stdio.h>
#include <stdlib.h>
int main() {
char str[] = "12345";
char *endptr;
long num;
num = strtol(str, &endptr, 10);
if (*endptr != '\0') {
printf("Conversion error: non-numeric characters\n");
return 1;
}
printf("Converted number: %ld\n", num);
return 0;
}
在此,strtol 使用基数 10 将字符串 "12345" 转换为长整数。endptr 通过指向第一个无效字符来帮助检测转换错误。我们检查 *endptr 是否为 null 终止符,以确保完全转换。这种方法比不提供错误检测的 atoi 安全得多。
处理不同的数字基数
strtol 可以转换各种基数的数字,如下例所示。
#include <stdio.h>
#include <stdlib.h>
int main() {
char hex_str[] = "1a3f";
char bin_str[] = "101011";
char *endptr;
long hex_num, bin_num;
hex_num = strtol(hex_str, &endptr, 16);
if (*endptr != '\0') {
printf("Hex conversion error\n");
return 1;
}
bin_num = strtol(bin_str, &endptr, 2);
if (*endptr != '\0') {
printf("Binary conversion error\n");
return 1;
}
printf("Hex %s = %ld\n", hex_str, hex_num);
printf("Binary %s = %ld\n", bin_str, bin_num);
return 0;
}
此示例转换了一个十六进制字符串(基数 16)和一个二进制字符串(基数 2)。第三个参数指定数字基数。基数 0 允许 strtol 从字符串前缀(十六进制的 0x,八进制的 0)自动检测基数。始终检查 endptr 以验证整个字符串是否成功转换。
使用 strtol 进行错误检测
此示例演示了对 strtol 进行全面的错误处理。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
int main() {
char str[] = "99999999999999999999";
char *endptr;
long num;
errno = 0;
num = strtol(str, &endptr, 10);
if (errno == ERANGE) {
printf("Number out of range\n");
if (num == LONG_MAX) printf("Overflow occurred\n");
if (num == LONG_MIN) printf("Underflow occurred\n");
return 1;
}
if (*endptr != '\0') {
printf("Conversion stopped at: %s\n", endptr);
return 1;
}
printf("Converted number: %ld\n", num);
return 0;
}
此代码显示了如何在转换非常大的数字时检测范围错误 (ERANGE)。我们会在转换后检查 errno 以识别溢出/下溢。该示例还演示了检查 endptr 以进行部分转换。适当的错误处理使 strtol 比简单的转换函数可靠得多。
从混合字符串解析数字
此示例展示了如何从包含非数字数据的字符串中提取数字。
#include <stdio.h>
#include <stdlib.h>
int main() {
char input[] = "values: 42, 17, 99, xyz";
char *ptr = input;
char *endptr;
long num;
// Skip non-numeric prefix
while (*ptr && (*ptr < '0' || *ptr > '9')) ptr++;
while (*ptr) {
num = strtol(ptr, &endptr, 10);
if (ptr == endptr) break; // No conversion
printf("Found number: %ld\n", num);
// Move to next potential number
ptr = endptr;
while (*ptr && (*ptr < '0' || *ptr > '9')) ptr++;
}
return 0;
}
此代码从包含混合内容的字符串中解析多个数字。它使用 endptr 在每次转换后推进字符串。循环会跳过数字之间的非数字字符。此技术对于处理配置文件或用户输入(其中数字出现在其他文本中)非常有用。该示例演示了 strtol 在实际解析场景中的灵活性。
安全替代方案:带输入验证的 strtol
此示例演示了一个用于更安全地使用 strtol 的包装器函数。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
int safe_strtol(const char *str, long *result) {
char *endptr;
if (str == NULL || *str == '\0') {
return 0; // Empty string
}
errno = 0;
*result = strtol(str, &endptr, 10);
if (errno == ERANGE) {
return 0; // Out of range
}
if (*endptr != '\0') {
return 0; // Extra characters
}
return 1; // Success
}
int main() {
char input[100];
long num;
printf("Enter a number: ");
fgets(input, sizeof(input), stdin);
if (safe_strtol(input, &num)) {
printf("Valid number: %ld\n", num);
} else {
printf("Invalid input\n");
}
return 0;
}
safe_strtol 函数提供全面的输入验证。它会检查空字符串、范围错误和尾随字符。此包装器使 strtol 在生产代码中的使用更加方便和安全。该示例展示了如何将其与来自 fgets 的用户输入一起使用。在处理不受信任的输入时,此类验证至关重要。
使用 strtol 的最佳实践
- 始终检查 errno:通过在转换后检查
errno来检测溢出/下溢。 - 检查 endptr:通过检查
*endptr来验证整个字符串是否已被转换。 - 初始化变量:确保正确初始化
endptr和errno。 - 选择合适的基数:选择正确的数字基数,或使用 0 进行自动检测。
- 考虑包装器:为常见的转换模式创建辅助函数。
来源
本教程探讨了 strtol 函数,从基本用法到高级错误处理。正确的字符串转换对于健壮的 C 程序至关重要,而 strtol 提供了可靠运行所需的工具。始终优先选择它,而不是像 atoi 这样更简单但不安全的替代方案。
作者
列表 C 标准库。