C atoi 函数
最后修改:2025 年 4 月 8 日
在 C 编程中,字符串到整数的转换是一项常见任务,而 `atoi` 是为此目的而设计的 But not safe function。本教程将深入介绍 `atoi`,包括其语法、用法和局限性。我们将探讨实际示例,并讨论 `strtol` 等更安全的替代方案,以实现健壮的应用程序。了解字符串转换函数有助于有效处理用户输入和文本数据。
什么是 atoi?
`atoi` 函数将字符串转换为整数。它声明在 `stdlib.h` 中,并接受一个参数:要转换的字符串。`atoi` 会跳过空白字符,然后转换后续字符,直到遇到非数字字符。它没有错误检测机制 - 无效输入返回 0。为了编写健壮的代码,建议使用 `strtol`,它提供错误检查并支持不同的数字基数。
基本的 atoi 用法
此示例演示了如何使用 `atoi` 转换简单的数字字符串。
#include <stdio.h>
#include <stdlib.h>
int main() {
char num_str[] = "12345";
int num = atoi(num_str);
printf("String: %s\n", num_str);
printf("Integer: %d\n", num);
return 0;
}
在这里,`atoi` 将字符串 "12345" 转换为整数 12345。该函数会自动处理前导空白字符。这对于格式良好的数字字符串效果很好。但是,它没有提供检测无效输入的方法。对于用户输入或不受信任的数据,请考虑更安全的替代方案。
处理无效输入
此示例显示了 `atoi` 对无效输入的行为。
#include <stdio.h>
#include <stdlib.h>
int main() {
char invalid1[] = "abc123";
char invalid2[] = "123abc";
printf("\"%s\" converts to %d\n", invalid1, atoi(invalid1));
printf("\"%s\" converts to %d\n", invalid2, atoi(invalid2));
return 0;
}
`atoi` 对不以数字开头的字符串("abc123")返回 0。它转换前导数字但会忽略尾随的非数字字符("123abc" 变为 123)。这种静默失败可能导致程序中的错误。该函数也不会检测溢出 - 大数字可能会返回意外的值。
安全替代方案:strtol
此示例演示了更安全的 `strtol` 函数。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main() {
char input[] = "123456789012345";
char *endptr;
long num;
errno = 0;
num = strtol(input, &endptr, 10);
if (errno == ERANGE) {
printf("Number out of range\n");
} else if (*endptr != '\0') {
printf("Invalid characters in input\n");
} else {
printf("Converted number: %ld\n", num);
}
return 0;
}
`strtol` 提供健壮的错误检查。它会在溢出时设置 `errno`,并返回指向第一个无效字符的指针。第三个参数指定数字的基数(10 表示十进制)。这使得 `strtol` 适用于需要输入验证的生产代码。
转换多个数字
此示例展示了如何从字符串中转换多个数字。
#include <stdio.h>
#include <stdlib.h>
int main() {
char data[] = "42 99 17";
int n1, n2, n3;
n1 = atoi(data);
n2 = atoi(data + 3);
n3 = atoi(data + 6);
printf("Numbers: %d, %d, %d\n", n1, n2, n3);
return 0;
}
在这里,我们通过调整传递给 `atoi` 的指针来转换三个以空格分隔的数字。当输入格式已知且一致时,这种方法有效。对于更复杂的解析,最好使用 `strtok` 结合 `strtol`。以这种方式使用 `atoi` 时,请务必验证结果。
处理负数
此示例演示了 `atoi` 对负数的处理。
#include <stdio.h>
#include <stdlib.h>
int main() {
char neg_str[] = "-32768";
char pos_str[] = "+2147483647";
printf("\"%s\" converts to %d\n", neg_str, atoi(neg_str));
printf("\"%s\" converts to %d\n", pos_str, atoi(pos_str));
return 0;
}
`atoi` 可以正确处理负数和可选的正号。它遵循与正数相同的转换规则。但是,它仍然缺乏溢出检测 - 非常大的负数可能会发生环绕。为了进行完整的范围检查,`strtol` 仍然是更好的选择。
字符串转换的最佳实践
- 为安全起见,请首选 strtol: 当输入验证很重要时,请使用 `strtol`。
- 检查溢出: `atoi` 会静默溢出 - 对于不受信任的输入来说很危险。
- 先验证输入: 使用 `atoi` 时,请事先验证字符串格式。
- 对于无符号数,请考虑 strtoul: 对于无符号整数,可以使用 `strtoul`。
- 处理基数转换: `strtol` 支持不同的基数(2-36)。
来源
本教程探讨了 `atoi` 函数,从基本用法到其局限性。虽然简单,但在输入验证和错误检测很重要的生产代码中,请务必考虑更安全的替代方案。
作者
列表 C 标准库。