C语言string转int,如何正确转换?

99ANYc3cd6
预计阅读时长 27 分钟
位置: 首页 C语言 正文

使用标准库函数 atoi (最简单但不安全)

atoi (ASCII to Integer) 是 C 标准库 <stdlib.h> 中提供的函数,专门用于将字符串转换为 int 类型。

string转int c语言
(图片来源网络,侵删)

函数原型

int atoi(const char *str);

功能

它会跳过字符串开头的空白字符(空格、制表符、换行符等),然后读取一个可选的正号 或负号 ,接着读取数字字符,直到遇到第一个非数字字符为止,最后将读取到的数字转换为整数并返回。

示例代码

#include <stdio.h>
#include <stdlib.h> // 必须包含此头文件
#include <string.h> // 用于 strlen 示例
int main() {
    const char *str1 = "12345";
    const char *str2 = "-678";
    const char *str3 = "  42 with text"; // 会忽略开头的空格,并停在 'w'
    const char *str4 = "abc123";          // 无法转换,返回 0
    const char *str5 = "99999999999999999999"; // 超出 int 范围,行为未定义
    int num1 = atoi(str1);
    int num2 = atoi(str2);
    int num3 = atoi(str3);
    int num4 = atoi(str4);
    int num5 = atoi(str5); // 危险!结果不可预测
    printf("'%s' -> %d\n", str1, num1);
    printf("'%s' -> %d\n", str2, num2);
    printf("'%s' -> %d\n", str3, num3);
    printf("'%s' -> %d\n", str4, num4);
    printf("'%s' -> %d (结果可能错误)\n", str5, num5);
    return 0;
}

优点

  • 简单易用:调用非常直接,一行代码就能完成转换。

缺点

  • 不安全:这是 atoi 最大的问题。
    1. 错误检测缺失:如果字符串不是以数字开头(如 str4),atoi 会返回 0,但你无法区分“转换成功,结果是 0”和“转换失败,返回默认值 0”这两种情况。
    2. 溢出处理缺失:如果转换后的数字超出了 int 类型的表示范围(如 str5),atoi 的行为是未定义(Undefined Behavior),这意味着它可能会返回一个错误的值、崩溃,或者产生任何意想不到的后果,这是非常危险的。

使用更安全的 strtol (推荐)

strtol (String to Long) 是 C 标准库 <stdlib.h> 中提供的另一个函数,功能更强大,也更安全,它可以将字符串转换为 long 类型,并且提供了完善的错误检测和溢出处理机制。

函数原型

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

参数详解

  1. str:要转换的字符串。
  2. endptr:这是一个指向 char* 指针的指针,函数执行后,*endptr 会指向转换停止时的字符位置,如果整个字符串都被成功转换,*endptr 将指向字符串的结尾 \0,这个参数是判断转换是否完全成功的关键。
  3. base:转换的基数(进制)。
    • base 为 0,函数会自动识别字符串的进制:
      • 0x0X 开头 -> 十六进制
      • 0 开头 -> 八进制
      • 其他 -> 十进制
    • base 为 2 到 36 之间的值,则按该进制转换。
    • base 为 1 或大于 36,则行为未定义。

返回值

  • 成功时,返回转换后的 long 整数值。
  • 如果转换的值超出了 long 类型的范围,函数会返回 LONG_MAXLONG_MIN(定义在 <limits.h> 中),并设置全局变量 errnoERANGE

示例代码

#include <stdio.h>
#include <stdlib.h> // for strtol, errno, LONG_MAX, LONG_MIN
#include <limits.h> // for LONG_MAX, LONG_MIN
#include <errno.h>   // for errno
int main() {
    const char *str1 = "12345";
    const char *str2 = "-678";
    const char *str3 = "  42 with text";
    const char *str4 = "abc123";
    const char *str5 = "99999999999999999999"; // 超出 long 范围
    char *endptr; // 用于接收转换停止的位置
    long num;
    // 转换 str1
    errno = 0; // 每次调用前重置 errno
    num = strtol(str1, &endptr, 10);
    if (errno == ERANGE) {
        printf("错误:数值超出 long 范围!\n");
    } else if (endptr == str1) {
        printf("错误:无法转换 '%s',没有数字字符\n", str1);
    } else {
        printf("'%s' -> %ld\n", str1, num);
    }
    // 转换 str2
    errno = 0;
    num = strtol(str2, &endptr, 10);
    if (errno == ERANGE) {
        printf("错误:数值超出 long 范围!\n");
    } else if (endptr == str2) {
        printf("错误:无法转换 '%s',没有数字字符\n", str2);
    } else {
        printf("'%s' -> %ld\n", str2, num);
    }
    // 转换 str3
    errno = 0;
    num = strtol(str3, &endptr, 10);
    if (errno == ERANGE) {
        printf("错误:数值超出 long 范围!\n");
    } else if (endptr == str3) {
        printf("错误:无法转换 '%s',没有数字字符\n", str3);
    } else {
        printf("'%s' -> %ld (剩余部分: '%s')\n", str3, num, endptr);
    }
    // 转换 str4
    errno = 0;
    num = strtol(str4, &endptr, 10);
    if (errno == ERANGE) {
        printf("错误:数值超出 long 范围!\n");
    } else if (endptr == str4) {
        printf("错误:无法转换 '%s',没有数字字符\n", str4);
    } else {
        printf("'%s' -> %ld\n", str4, num);
    }
    // 转换 str5
    errno = 0;
    num = strtol(str5, &endptr, 10);
    if (errno == ERANGE) {
        printf("错误:'%s' 数值超出 long 范围!\n", str5);
    } else if (endptr == str5) {
        printf("错误:无法转换 '%s',没有数字字符\n", str5);
    } else {
        printf("'%s' -> %ld\n", str5, num);
    }
    return 0;
}

优点

  • 安全可靠:通过 endptrerrno 可以精确地判断转换是否成功、是否溢出。
  • 功能强大:可以处理各种进制,并且能告诉你转换到哪里停止了。

缺点

  • atoi 稍微复杂一些,需要理解 endptrerrno 的用法。

手动实现 (最灵活,但需要自己处理所有细节)

如果你不想依赖标准库,或者需要实现一些特殊的转换逻辑(比如只允许特定的数字格式),可以自己编写转换函数。

基本思路

  1. 跳过前导空格。
  2. 处理可选的正负号。
  3. 遍历后续的数字字符,将它们拼凑成数值。
  4. 检查是否溢出。
  5. 遇到非数字字符时停止。

示例代码

#include <stdio.h>
#include <ctype.h> // for isdigit
#include <limits.h> // for INT_MAX, INT_MIN
int my_str_to_int(const char *str) {
    int sign = 1; // 默认为正数
    int result = 0;
    int i = 0;
    // 1. 跳过前导空格
    while (isspace(str[i])) {
        i++;
    }
    // 2. 处理正负号
    if (str[i] == '-') {
        sign = -1;
        i++;
    } else if (str[i] == '+') {
        i++;
    }
    // 3. 遍历数字字符
    while (isdigit(str[i])) {
        int digit = str[i] - '0'; // 将字符 '0'-'9' 转换为 0-9
        // 4. 检查正数溢出
        if (sign == 1 && result > (INT_MAX - digit) / 10) {
            // result * 10 + digit 会大于 INT_MAX
            return INT_MAX; // 返回 int 的最大值
        }
        // 5. 检查负数溢出
        if (sign == -1 && result > (INT_MAX - digit) / 10) {
            // 这里需要特殊处理,因为 INT_MIN 的绝对值比 INT_MAX 大 1
            // result * 10 + digit >= -(INT_MIN),则溢出
            // 简化为:result > (INT_MAX - digit) / 10
            return INT_MIN; // 返回 int 的最小值
        }
        result = result * 10 + digit;
        i++;
    }
    return sign * result;
}
int main() {
    const char *str1 = "12345";
    const char *str2 = "-678";
    const char *str3 = "  42";
    const char *str4 = "abc123";
    const char *str5 = "2147483647"; // INT_MAX
    const char *str6 = "2147483648"; // 比 INT_MAX 大 1
    printf("'%s' -> %d\n", str1, my_str_to_int(str1));
    printf("'%s' -> %d\n", str2, my_str_to_int(str2));
    printf("'%s' -> %d\n", str3, my_str_to_int(str3));
    printf("'%s' -> %d\n", str4, my_str_to_int(str4));
    printf("'%s' -> %d\n", str5, my_str_to_int(str5));
    printf("'%s' -> %d (溢出,返回 INT_MIN)\n", str6, my_str_to_int(str6));
    return 0;
}

优点

  • 完全控制:你可以自定义转换逻辑,例如不允许前导空格,或者自定义错误处理方式。
  • 不依赖库函数:在某些嵌入式或特殊环境下可能有用。

缺点

  • 复杂且容易出错:你需要自己处理所有边界情况,包括前导空格、正负号、各种进制的可能性以及最重要的溢出检测,手动实现一个健壮的转换函数非常困难。

总结与建议

方法 优点 缺点 推荐场景
atoi 极其简单 不安全,无法检测错误和溢出 强烈不推荐用于任何生产代码,仅用于非常简单的、确定输入绝对可靠的脚本或一次性程序。
strtol 安全可靠,功能强大,可检测错误和溢出 atoi 稍复杂 强烈推荐,这是 C 语言中将字符串转换为整数的标准、安全、正确的方式。
手动实现 完全控制,灵活 复杂,极易出错,需要自己处理所有细节 当有特殊需求(如自定义格式)或在不允许使用标准库的极端环境下。

最终建议:

string转int c语言
(图片来源网络,侵删)

在 C 语言开发中,请始终优先使用 strtol 函数,它虽然比 atoi 多两个参数,但带来的安全性和可靠性是完全值得的,它能帮助你写出更健壮、更不容易出错的代码,只有在 strtol 无法满足你的特殊需求时,才考虑自己动手实现。

string转int c语言
(图片来源网络,侵删)
-- 展开阅读全文 --
头像
dede如何关闭生成html5?
« 上一篇 02-13
dedecms织梦视频怎么用?
下一篇 » 02-13
取消
微信二维码
支付宝二维码

目录[+]