C strtoull 函数
最后修改:2025 年 4 月 8 日
字符串到数字的转换是 C 编程中一项常见的任务,而 `strtoull` 提供了一种可靠的方法将字符串转换为无符号长长整型。本教程将深入介绍 `strtoull`,包括其语法、用法和错误处理。我们将探讨实际示例,并讨论为什么它比 `atoll` 等替代方法更安全。理解 `strtoull` 有助于创建更可靠且能正确处理数字输入的程序。
什么是 strtoull?
`strtoull` 函数将字符串转换为无符号长长整型。它声明在 `stdlib.h` 中,并提供强大的错误处理功能。与 `atoll` 不同,它可以检测转换错误并支持不同的数字基数。该函数接受三个参数:输入字符串、可选的结束指针和数字基数(0 到 36)。它返回转换后的值,在出错时返回 0,并将 `errno` 设置为指示特定问题。
strtoull 的基本用法
此示例演示了将简单的十进制字符串转换为无符号长长整型。
#include <stdio.h> #include <stdlib.h> #include <errno.h> int main() { const char *num_str = "18446744073709551615"; char *endptr; unsigned long long num; errno = 0; num = strtoull(num_str, &endptr, 10); if (errno == ERANGE) { printf("Number out of range\n"); return 1; } else if (*endptr != '\0') { printf("Invalid characters in input\n"); return 1; } printf("Converted number: %llu\n", num); return 0; }
在这里,`strtoull` 将 64 位无符号最大值从字符串中转换出来。我们检查 `errno` 是否有范围错误,并检查 `endptr` 是否包含无效字符。基数 10 指定十进制转换。这种方法比 `atoll` 安全得多,`atoll` 不提供错误检测。在使用转换结果之前,请务必验证它。
十六进制转换
`strtoull` 在指定基数 16 时可以转换十六进制字符串。
#include <stdio.h> #include <stdlib.h> #include <errno.h> int main() { const char *hex_str = "0xFFFFFFFFFFFFFFFF"; char *endptr; unsigned long long num; errno = 0; num = strtoull(hex_str, &endptr, 16); if (errno == ERANGE) { printf("Number out of range\n"); return 1; } else if (*endptr != '\0' && *endptr != '\n') { printf("Invalid characters in input\n"); return 1; } printf("Hexadecimal %s = %llu in decimal\n", hex_str, num); return 0; }
此示例将十六进制字符串转换为无符号长长整型。基数 16 参数启用十六进制转换,“0x”前缀是允许的,但不是必需的。我们检查 `errno` 和 `endptr` 是否存在错误。请注意,十六进制字母可以是大小写。该函数在尝试转换之前会跳过前导空格。
自动基数检测
当指定基数 0 时,`strtoull` 会自动检测数字基数。
#include <stdio.h> #include <stdlib.h> #include <errno.h> int main() { const char *inputs[] = {"42", "052", "0x2A", NULL}; char *endptr; unsigned long long num; for (int i = 0; inputs[i] != NULL; i++) { errno = 0; num = strtoull(inputs[i], &endptr, 0); if (errno == ERANGE) { printf("%s: Number out of range\n", inputs[i]); continue; } else if (*endptr != '\0') { printf("%s: Invalid characters\n", inputs[i]); continue; } printf("%s = %llu (auto-detected base)\n", inputs[i], num); } return 0; }
使用基数 0 时,`strtoull` 会像标准的 C 常量一样解释数字:默认情况下为十进制,以 0 为前缀时为八进制,以 0x 为前缀时为十六进制。此示例自动转换十进制、八进制和十六进制字符串。当输入格式事先未知时,该函数提供了灵活性。使用自动基数检测时,请务必验证转换结果。
使用 strtoull 进行错误处理
此示例演示了使用 `strtoull` 进行全面的错误处理。
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <limits.h> int main() { const char *test_cases[] = { "12345678901234567890", // Valid "99999999999999999999", // Too large "12abc", // Partial conversion " -123", // Negative (allowed but clamped) NULL }; char *endptr; for (int i = 0; test_cases[i] != NULL; i++) { errno = 0; unsigned long long num = strtoull(test_cases[i], &endptr, 10); printf("Input: \"%s\"\n", test_cases[i]); printf("Converted: %llu\n", num); if (errno == ERANGE) { printf("Error: Number out of range (ERANGE)\n"); } if (*endptr != '\0') { printf("Warning: Stopped at invalid character '%c'\n", *endptr); } if (test_cases[i] == endptr) { printf("Error: No conversion performed\n"); } printf("\n"); } return 0; }
此示例展示了使用 `strtoull` 的各种错误情况。我们测试有效数字、溢出、部分转换和负值。技术上允许负数,但会转换为其无符号等效值。`endptr` 有助于识别转换停止的位置。多重检查为健壮的输入处理提供了完整的错误检测。
使用不同基数的 strtoull
`strtoull` 支持从 2 到 36 的基数转换。
#include <stdio.h> #include <stdlib.h> #include <errno.h> int main() { const char *binary = "101010"; const char *ternary = "2101"; const char *base36 = "z3kq"; char *endptr; unsigned long long num; // Binary conversion (base 2) num = strtoull(binary, &endptr, 2); printf("Binary %s = %llu\n", binary, num); // Ternary conversion (base 3) num = strtoull(ternary, &endptr, 3); printf("Ternary %s = %llu\n", ternary, num); // Base36 conversion (digits 0-9, letters a-z) num = strtoull(base36, &endptr, 36); printf("Base36 %s = %llu\n", base36, num); return 0; }
此示例演示了使用不同数字基数的 `strtoull`。基数 2 转换二进制字符串,基数 3 处理三进制,基数 36 支持字母数字(0-9,a-z)。字母可以是大小写。该函数为解析各种格式的数字提供了极大的灵活性。请记住,大于 10 的基数使用字母作为附加数字(a=10,b=11,依此类推)。
使用 strtoull 的最佳实践
- 始终检查 errno: 调用前将 errno 设置为 0,之后检查 ERANGE。
- 检查 endptr: 验证转换停止的位置,以检测无效字符。
- 优先使用 strtoull 而非 atoll: strtoull 比 atoll 提供更好的错误处理。
- 谨慎处理负数: 负值将被转换为其无符号等效值。
- 考虑区域设置: 某些区域设置使用不同的数字字符。
来源
本教程探讨了 `strtoull` 函数,从基本用法到高级错误处理。正确的字符串到数字转换对于安全可靠的 C 程序至关重要。在处理数字转换时,请始终验证输入并处理潜在的错误。
作者
列表 C 标准库。