0

0

c++如何将字符串转换为整数_c++字符串转整数常用方法汇总

裘德小鎮的故事

裘德小鎮的故事

发布时间:2025-10-16 20:49:02

|

583人浏览过

|

来源于php中文网

原创

C++中字符串转整数推荐使用std::stoi,因其支持异常处理和部分转换检测;std::istringstream适用于解析含多个数值或复杂格式的字符串;atoi和sscanf虽性能略优但缺乏安全机制,不推荐用于现代C++。

c++如何将字符串转换为整数_c++字符串转整数常用方法汇总

在C++中将字符串转换为整数,主要有几种方法,每种都有其适用场景和特点。最推荐且现代C++风格的是使用std::stoi,它不仅简洁,还提供了良好的错误处理机制。此外,std::istringstream提供了更灵活的流式解析能力,而C风格的atoisscanf在特定场景下也有其用武之地,但通常伴随着更多的风险。选择哪种方法,往往需要权衡安全性、便利性和对错误的容忍度。

解决方案

将C++字符串转换为整数,我们可以从几个不同的角度入手,每种方法都有其独特的哲学和实践考量。

1. 使用 std::stoi (C++11及更高版本)

这是现代C++中最推荐的方法。std::stoi 函数位于 <string> 头文件中,它能够将 std::string 对象转换为 int。它的强大之处在于提供了异常机制来处理无效输入或超出范围的数值。

立即学习C++免费学习笔记(深入)”;

#include <iostream>
#include <string>
#include <stdexcept> // For std::invalid_argument, std::out_of_range

// 示例:将字符串 "123" 转换为整数
std::string str1 = "123";
try {
    int num1 = std::stoi(str1);
    std::cout << "stoi(\"" << str1 << "\"): " << num1 << std::endl; // 输出: 123
} catch (const std::invalid_argument& e) {
    std::cerr << "无效参数: " << e.what() << std::endl;
} catch (const std::out_of_range& e) {
    std::cerr << "超出范围: " << e.what() << std::endl;
}

// 示例:包含非数字字符的字符串
std::string str2 = "123abc";
try {
    // stoi 会尝试转换开头的数字部分,并返回转换后的值
    // 如果需要严格检查整个字符串,可以结合第二个参数pos
    size_t pos;
    int num2 = std::stoi(str2, &pos);
    std::cout << "stoi(\"" << str2 << "\"): " << num2 << std::endl; // 输出: 123
    if (pos != str2.length()) {
        std::cout << "注意: 字符串 \"" << str2 << "\" 在位置 " << pos << " 之后包含非数字字符。" << std::endl;
    }
} catch (const std::invalid_argument& e) {
    std::cerr << "无效参数: " << e.what() << std::endl;
} catch (const std::out_of_range& e) {
    std::cerr << "超出范围: " << e.what() << std::endl;
}

// 示例:完全非数字的字符串
std::string str3 = "hello";
try {
    int num3 = std::stoi(str3); // 会抛出 std::invalid_argument
    std::cout << "stoi(\"" << str3 << "\"): " << num3 << std::endl;
} catch (const std::invalid_argument& e) {
    std::cerr << "无效参数 (预期): " << e.what() << std::endl; // 输出: 无效参数 (预期): stoi
} catch (const std::out_of_range& e) {
    std::cerr << "超出范围: " << e.what() << std::endl;
}

// 示例:超出 int 范围的字符串
std::string str4 = "2147483648"; // 2^31, 超过 int 最大值 (通常是 2147483647)
try {
    int num4 = std::stoi(str4); // 会抛出 std::out_of_range
    std::cout << "stoi(\"" << str4 << "\"): " << num4 << std::endl;
} catch (const std::invalid_argument& e) {
    std::cerr << "无效参数: " << e.what() << std::endl;
} catch (const std::out_of_range& e) {
    std::cerr << "超出范围 (预期): " << e.what() << std::endl; // 输出: 超出范围 (预期): stoi
}

std::stoi 的第二个可选参数 pos 是一个 size_t* 指针,用于存储转换结束时字符串中下一个字符的索引。这对于检查字符串是否完全由数字组成非常有用。

2. 使用 std::istringstream

std::istringstream 是一个基于字符串的输入流,它提供了类似于 std::cin 的功能,可以从字符串中提取各种类型的数据。这在处理更复杂的字符串解析任务时非常灵活。

#include <iostream>
#include <string>
#include <sstream> // For std::istringstream

std::string str = "456";
int num;
std::istringstream iss(str);
iss >> num;

if (iss.fail()) { // 检查转换是否失败
    std::cerr << "istringstream 转换失败。" << std::endl;
} else {
    std::cout << "istringstream(\"" << str << "\"): " << num << std::endl; // 输出: 456
}

// 示例:处理带非数字字符的字符串
std::string str_bad = "789abc";
int num_bad;
std::istringstream iss_bad(str_bad);
iss_bad >> num_bad;

if (iss_bad.fail()) {
    std::cerr << "istringstream 转换失败,可能包含非数字字符或格式不正确。" << std::endl;
} else {
    std::cout << "istringstream(\"" << str_bad << "\"): " << num_bad << std::endl; // 输出: 789
    // 同样,如果需要严格检查,可以检查流中是否还有剩余字符
    char remaining_char;
    if (iss_bad >> remaining_char) {
        std::cout << "注意: 字符串 \"" << str_bad << "\" 转换后还有剩余字符。" << std::endl;
    }
}

std::istringstream 的优点在于其通用性,不仅可以转换为 int,还可以转换为 floatdouble 或其他自定义类型。通过检查 iss.fail()iss.good() 可以判断转换是否成功。

3. 使用 atoi (C风格函数)

atoi (ASCII to integer) 是一个C风格的函数,位于 <cstdlib> 头文件中。它将C风格字符串(const char*)转换为 int

#include <iostream>
#include <string>
#include <cstdlib> // For atoi

std::string str_c = "789";
int num_c = std::atoi(str_c.c_str()); // 需要转换为 C 风格字符串
std::cout << "atoi(\"" << str_c << "\"): " << num_c << std::endl; // 输出: 789

// 示例:包含非数字字符的字符串
std::string str_c_bad = "123xyz";
int num_c_bad = std::atoi(str_c_bad.c_str());
std::cout << "atoi(\"" << str_c_bad << "\"): " << num_c_bad << std::endl; // 输出: 123

// 示例:完全非数字的字符串
std::string str_c_invalid = "hello";
int num_c_invalid = std::atoi(str_c_invalid.c_str());
std::cout << "atoi(\"" << str_c_invalid << "\"): " << num_c_invalid << std::endl; // 输出: 0

atoi 的主要缺点是它不提供任何错误检查机制。如果字符串无法转换为有效的整数,它会返回 0,但这与字符串本身就是 "0" 的情况无法区分。此外,如果转换结果超出 int 的表示范围,atoi 的行为是未定义的。因此,在需要健壮错误处理的现代C++代码中,通常不推荐使用 atoi

4. 使用 sscanf (C风格函数)

sscanf 也是一个C风格函数,位于 <cstdio> 头文件中,它从字符串中读取格式化的数据。

LLaMA
LLaMA

Meta公司发布的下一代开源大型语言模型

下载
#include <iostream>
#include <string>
#include <cstdio> // For sscanf

std::string str_s = "101";
int num_s;
int result = std::sscanf(str_s.c_str(), "%d", &num_s);

if (result == 1) { // 检查是否成功匹配了一个项
    std::cout << "sscanf(\"" << str_s << "\"): " << num_s << std::endl; // 输出: 101
} else {
    std::cerr << "sscanf 转换失败。" << std::endl;
}

// 示例:包含非数字字符的字符串
std::string str_s_bad = "202abc";
int num_s_bad;
result = std::sscanf(str_s_bad.c_str(), "%d", &num_s_bad);
if (result == 1) {
    std::cout << "sscanf(\"" << str_s_bad << "\"): " << num_s_bad << std::endl; // 输出: 202
    // sscanf 也会在遇到非数字字符时停止,需要额外检查字符串是否完全转换
} else {
    std::cerr << "sscanf 转换失败。" << std::endl;
}

sscanfatoi 提供了更精细的控制和错误报告(通过返回值),但它仍然是C风格的,不如 std::stoistd::istringstream 那样与C++的类型系统和异常机制融合得好。

std::stoi 在处理错误时有哪些优势?

std::stoi 在C++字符串转整数的方法中,其错误处理能力是其最显著的优势,这让它在现代C++编程中成为首选。它的优势主要体现在两个方面:

首先,异常机制std::stoi 在遇到无法转换的字符串(如 "hello")时,会抛出 std::invalid_argument 异常。而当转换结果超出 int 类型所能表示的范围(溢出或下溢)时,它会抛出 std::out_of_range 异常。这种基于异常的错误报告机制,与C++的异常处理流程完美契合,使得程序能够清晰地捕获并处理这些非正常情况,而不是默默地返回一个可能被误解的错误值(比如 atoi 返回 0)。

例如,考虑这样的场景:你从用户输入或配置文件中读取一个字符串,期望它是一个整数。如果用户不小心输入了 "ten" 或者一个天文数字,std::stoi 会立即通过异常告知你问题所在,你可以据此给用户友好的提示,或者采取其他恢复措施。如果使用 atoi,"ten" 会被转换为 0,而 "0" 也是一个合法的整数,这就会导致逻辑上的混淆,难以判断是用户真的输入了 0 还是输入了无效字符。

其次,部分转换的精确控制std::stoi 提供了可选的 size_t* pos 参数。这个参数能够指示字符串中哪个位置停止了转换。这意味着,即使字符串是 "123abc",std::stoi 也能告诉你它成功转换了 "123",并且在索引 3 处遇到了非数字字符 'a'。这对于需要解析混合了数字和非数字内容的字符串非常有用,你可以根据 pos 的值来判断整个字符串是否都被成功解析,或者哪些部分是有效的数字。

#include <iostream>
#include <string>
#include <stdexcept>

void convertAndCheck(const std::string& s) {
    try {
        size_t pos;
        int value = std::stoi(s, &pos);
        std::cout << "字符串: \"" << s << "\", 转换为整数: " << value << std::endl;
        if (pos < s.length()) {
            std::cout << "注意: 字符串在位置 " << pos << " 之后还有非数字字符: \"" << s.substr(pos) << "\"" << std::endl;
        }
    } catch (const std::invalid_argument& e) {
        std::cerr << "错误: 无效输入 - \"" << s << "\" 无法转换为整数。详情: " << e.what() << std::endl;
    } catch (const std::out_of_range& e) {
        std::cerr << "错误: 数值超出范围 - \"" << s << "\" 太大或太小。详情: " << e.what() << std::endl;
    }
    std::cout << "------------------------" << std::endl;
}

// 调用示例
// convertAndCheck("123");
// convertAndCheck("-45");
// convertAndCheck("0");
// convertAndCheck("  99  "); // 会忽略前导和尾随空格
// convertAndCheck("123test");
// convertAndCheck("test123"); // 抛出 invalid_argument
// convertAndCheck("2147483648"); // 抛出 out_of_range (假设 int 为 32 位)
// convertAndCheck("-2147483649"); // 抛出 out_of_range

总的来说,std::stoi 通过明确的异常类型和灵活的 pos 参数,提供了一种安全、可控且符合现代C++编程范式的字符串到整数转换方案,极大地提升了代码的健壮性和可维护性。

std::istringstream 适用于哪些更复杂的场景?

std::istringstream 的强大之处在于它模拟了一个输入流,这意味着它不仅能做简单的字符串到整数转换,还能处理更复杂、更像自然语言的解析任务。把它想象成一个可以从内存中的字符串读取数据的 std::cin,这样它的应用场景就一下子开阔了。

1. 解析包含多个数值或不同类型数据的字符串: 如果你的字符串不仅仅是一个数字,而是像 "Width: 100 Height: 200 Depth: 50" 这样的格式,或者 "Point(10, 20)",std::istringstream 就能轻松应对。你可以像从文件中读取数据一样,使用 >> 运算符连续提取数据。

#include <iostream>
#include <string>
#include <sstream>

std::string configLine = "Resolution: 1920x1080 RefreshRate: 144Hz";
std::istringstream iss(configLine);
std::string label1, resolutionStr, label2, refreshRateStr;
int width, height, refreshRate;
char x_char; // 用于捕获 'x'

// 尝试解析 "Resolution: 1920x1080"
if (iss >> label1 && label1 == "Resolution:") {
    if (iss >> width >> x_char && x_char == 'x' && iss >> height) {
        std::cout << "解析到分辨率: " << width << "x" << height << std::endl;
    } else {
        std::cerr << "解析分辨率失败。" << std::endl;
    }
} else {
    std::cerr << "未找到 Resolution 标签。" << std::endl;
}

// 尝试解析 "RefreshRate: 144Hz"
if (iss >> label2 && label2 == "RefreshRate:") {
    // 这里可以使用字符串来读取 "144Hz",然后进一步处理
    // 或者直接尝试读取整数,如果后面有非数字字符,流会进入失败状态
    if (iss >> refreshRate) {
        std::cout << "解析到刷新率: " << refreshRate << "Hz" << std::endl;
        // 检查是否有剩余字符,如 'Hz'
        std::string unit;
        iss >> unit; // 尝试读取单位
        if (!iss.fail() && unit == "Hz") {
            std::cout << "单位 'Hz' 也被成功识别。" << std::endl;
        }
    } else {
        std::cerr << "解析刷新率失败。" << std::endl;
    }
} else {
    std::cerr << "未找到 RefreshRate 标签。" << std::endl;
}

2. 灵活的错误检查和状态管理:std::istringstream 作为流,拥有 fail(), bad(), eof(), good() 等方法来检查流的状态。这在解析复杂或格式不固定的字符串时非常有用。你可以根据流的状态来判断是数据格式不匹配、到达字符串末尾还是发生了更严重的错误。

3. 将字符串转换为非基本类型: 如果你有自定义的类型,并且为其重载了 operator>>,那么 std::istringstream 也能无缝地将字符串内容解析到你的自定义对象中。这使得它在处理序列化/反序列化任务时非常方便。

4. 避免字符串拷贝的性能考量 (虽然不总是最快,但概念上灵活): 虽然创建 std::istringstream 对象本身有开销,但在某些场景下,如果需要对一个长字符串进行多次不同模式的解析,或者需要逐词、逐行地处理,使用流的方式可以避免反复创建子字符串或进行其他字符串操作,从而在概念上提供一种更“流式”的、可能更高效的解析方式。

简单来说,当你的字符串不仅仅是一个裸数字,而是包含了结构、分隔符、多个数据点,或者需要进行更细致的错误判断和分步解析时,std::istringstream 就能大显身手。它提供了一种面向对象的、更C++化的字符串解析范式,让代码更具可读性和扩展性。

性能考量:在不同转换方法间如何选择?

在字符串到整数的转换中,性能确实是一个值得探讨的问题,但我们首先要明确,对于绝大多数应用程序而言,代码的清晰度、健壮性和正确性远比微小的性能差异更重要。只有在遇到性能瓶颈,并且分析表明字符串转换是主要瓶CPU时间的地方,我们才需要深入研究性能。

1. std::stoi 通常,std::stoi 是一个经过高度优化的函数。它在内部实现上会利用一些高效的字符处理技术。对于单次、直接的字符串到整数转换,它的性能表现非常出色,并且由于其异常处理机制,它在安全性上提供了最好的平衡。它的开销主要在于异常处理路径,如果预期会有很多无效输入导致频繁抛出异常,这可能会有额外的性能成本。但对于大部分有效转换,其性能是足够快的。

2. std::istringstreamstd::istringstream 涉及到流对象的构建、虚拟函数调用以及更复杂的内部状态管理,因此它的理论开销通常会比 std::stoi 稍大。每次转换都需要创建一个 istringstream 对象,这本身就是一种开销。然而,这种开销对于大多数应用程序来说是微不足道的。它的优势在于解析复杂格式的字符串,如果你的任务是解析多个值或混合类型,那么 istringstream 的整体效率可能更高,因为它避免了多次的字符串切分和单独转换。如果你需要从一个字符串中提取多个整数,使用一个 istringstream 对象循环提取,其总性能可能优于多次调用 std::stoi

3. atoisscanfatoisscanf 是C风格的函数,它们通常被认为在纯粹的转换速度上可能略快,因为它们不涉及C++的异常处理机制或流对象的开销。atoi 是最简单的,但它的严重缺点是没有错误报告,这使得它在现代C++中几乎不应该被用于任何需要可靠性检查的场景。sscanf 提供了更多的控制,其性能也通常不错,但它需要C风格的字符串 (const char*),并且其错误处理通过返回值进行,不如异常直观。

如何选择?

  • 首选 std::stoi 在大多数情况下,如果只需要将一个 std::string 转换为一个整数,并且需要健壮的错误处理(包括无效输入和数值溢出),std::stoi 是最佳选择。它的性能足够好,并且提供了现代C++应有的安全性。
  • 复杂解析选 std::istringstream 如果你需要从一个字符串中

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1031

2023.08.02

css中float用法
css中float用法

css中float属性允许元素脱离文档流并沿其父元素边缘排列,用于创建并排列、对齐文本图像、浮动菜单边栏和重叠元素。想了解更多float的相关内容,可以阅读本专题下面的文章。

595

2024.04.28

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

108

2025.10.23

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1567

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

241

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

150

2025.10.17

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

58

2025.09.05

java面向对象
java面向对象

本专题整合了java面向对象相关内容,阅读专题下面的文章了解更多详细内容。

63

2025.11.27

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

37

2026.03.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 11.2万人学习

C 教程
C 教程

共75课时 | 5.4万人学习

C++教程
C++教程

共115课时 | 21.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号