C++ 整数和字符串转换函数总结

一、C++11 及以后的标准库方法

1. 整数转字符串

// 1. std::to_string() - 最常用
std::string to_string(int value);
std::string to_string(long value);
std::string to_string(long long value);
std::string to_string(unsigned value);
std::string to_string(float value);
std::string to_string(double value);

// 示例
std::string s1 = std::to_string(42);           // "42"
std::string s2 = std::to_string(3.14159);      // "3.141590"

2. 字符串转整数

// 带错误处理的转换函数
int std::stoi(const std::string& str, size_t* pos = 0, int base = 10);   //2/8/10/16
long std::stol(const std::string& str, size_t* pos = 0, int base = 10);	//2/8/10/16
long long std::stoll(const std::string& str, size_t* pos = 0, int base = 10);		//2/8/10/16
unsigned long std::stoul(const std::string& str, size_t* pos = 0, int base = 10);	//2/8/10/16
unsigned long long stoull(const std::string& str, size_t* pos = 0, int base = 10);	//2/8/10/16
float stof(const string& str, size_t* pos = nullptr);	//仅十进制
double stod(const string& str, size_t* pos = nullptr);	//仅十进制


// 示例
std::string s = "123abc";
size_t pos;
int num = std::stoi(s, &pos);  // num = 123, pos = 3
参数详细说明
  1. str (必需参数)
  • 类型: const std::string& (常量引用)
  • 含义: 要转换的输入字符串
  • 说明: 包含数字表示的字符串,函数会解析其内容
  1. pos (可选参数)
  • 类型: size_t* (指向 size_t 类型的指针)
  • 默认值: 0 (即 nullptr)
  • 含义: 存储第一个未转换字符的位置索引
  • 作用:
    • 如果提供非空指针,函数会将第一个无法转换的字符的索引存入 *pos
    • 可用于检查转换是否消耗了整个字符串
    • 如果为 nullptr,则忽略此信息
  1. base (可选参数)
  • 类型: int
  • 默认值: 10
  • 含义: 数字的进制基数
  • 取值范围: 0236
    • base = 0: 自动检测进制(类似C语言的规则)
      • 0x0X 开头 → 十六进制(base 16)
      • 0 开头 → 八进制(base 8)
      • 其他 → 十进制(base 10)
    • base = 2~36: 使用指定进制
详细示例
  • 示例1:基本用法
#include <iostream>
#include <string>

std::string str = "123abc";
size_t pos;
int num = std::stoi(str, &pos);  // pos = 3

std::cout << "数值: " << num << std::endl;      // 123
std::cout << "未转换位置: " << pos << std::endl; // 3
std::cout << "剩余字符串: " << str.substr(pos) << std::endl; // "abc"
  • 示例2:不同进制
std::string str;

// 十进制(默认)
str = "255";
int dec = std::stoi(str);                    // 255
int dec2 = std::stoi(str, nullptr, 10);      // 255

// 十六进制
str = "FF";
int hex = std::stoi(str, nullptr, 16);       // 255

// 八进制
str = "377";
int oct = std::stoi(str, nullptr, 8);        // 255

// 二进制(base=2)
str = "11111111";
int bin = std::stoi(str, nullptr, 2);        // 255

// 自动检测(base=0)
str = "0xFF";
int auto1 = std::stoi(str, nullptr, 0);      // 255(自动识别十六进制)
str = "0377";
int auto2 = std::stoi(str, nullptr, 0);      // 255(自动识别八进制)
str = "255";
int auto3 = std::stoi(str, nullptr, 0);      // 255(十进制)
  • 示例3:完整转换检查
#include <iostream>
#include <string>

void parseNumber(const std::string& input) {
    size_t pos;
    try {
        long long num = std::stoll(input, &pos);
        
        std::cout << "输入: \"" << input << "\"" << std::endl;
        std::cout << "转换数值: " << num << std::endl;
        std::cout << "已转换字符数: " << pos << std::endl;
        
        if (pos == input.length()) {
            std::cout << "✓ 整个字符串都被转换" << std::endl;
        } else {
            std::cout << "✗ 部分转换,剩余: \"" 
                      << input.substr(pos) << "\"" << std::endl;
        }
    } catch (const std::invalid_argument& e) {
        std::cout << "✗ 无效参数: 无法转换为数字" << std::endl;
    } catch (const std::out_of_range& e) {
        std::cout << "✗ 数值超出范围" << std::endl;
    }
    std::cout << std::endl;
}

int main() {
    parseNumber("123");           // 完全转换
    parseNumber("123abc");        // 部分转换,剩余"abc"
    parseNumber("  456");         // 注意:会自动跳过前导空白
    parseNumber("abc123");        // 无效参数(以非数字开头)
    parseNumber("99999999999999999999"); // 超出范围
    
    return 0;
}
  • 示例4:处理空格和空白
std::string str = "  123  ";
size_t pos;
// stoi 会自动跳过前导空白字符(空格、制表符等)
int num = std::stoi(str, &pos);  
std::cout << num << std::endl;   // 123
std::cout << pos << std::endl;   // 5 (第一个'3'后面的空格位置)
  • 示例5:stoi vs stoll 的区别
// stoi: 返回 int (通常是32位)
std::string large = "3000000000";  // 30亿
try {
    int small = std::stoi(large);  // 可能溢出(取决于平台)
} catch (const std::out_of_range& e) {
    std::cout << "int 太小,无法存储" << std::endl;
}

// stoll: 返回 long long (至少64位)
long long big = std::stoll(large);  // 成功,3000000000
重要特性
特性 说明
前导空白 自动跳过(空格、制表符、换行符等)
正负号 支持 +- 前缀
进制前缀 base=0 时识别 0x/0X(十六进制) 和 0(八进制)
停止条件 遇到非数字字符时停止(根据进制)
异常 std::invalid_argument:无有效转换
std::out_of_range:超出范围
常见用法模式
// 模式1:只转换,不关心剩余部分
int value = std::stoi("123abc");  // value = 123

// 模式2:检查是否完全转换
size_t pos;
int value = std::stoi("123", &pos);
if (pos == str.length()) {
    // 完全转换成功
}

// 模式3:解析带单位的值
std::string data = "1024MB";
size_t pos;
int num = std::stoi(data, &pos);  // num = 1024
std::string unit = data.substr(pos);  // unit = "MB"

// 模式4:十六进制解析
std::string hexColor = "0xFF0000";
int red = std::stoi(hexColor, nullptr, 0);  // 自动识别十六进制
性能提示
  • 使用 pos 参数可避免不必要的字符串拷贝
  • 对于性能敏感代码,考虑使用 std::from_chars (C++17)
  • 如果需要转换C风格字符串,直接用 std::strtol 可能更高效

二、字符串流方法(通用但较慢)

#include <sstream>

// 任意类型转字符串
std::ostringstream oss;
oss << 123;
std::string s = oss.str();

// 字符串转整数
std::istringstream iss("456");
int n;
iss >> n;

三、C++20 新增

// std::format (C++20) - 类似Python的format
#include <format>
std::string s = std::format("{:d}", 42);           // "42"
std::string s = std::format("{:#x}", 255);         // "0xff"

四、性能对比和使用建议

方法 性能 适用场景
to_string/stoi 中等 一般用途,代码简洁
stringstream 较慢 复杂格式化或多种类型组合
sprintf 较快 C风格代码,需注意缓冲区安全
format (C++20) 中等 需要复杂格式化时

五、完整示例

#include <iostream>
#include <string>
#include <charconv>
#include <format>

int main() {
    // 整数转字符串
    std::string s1 = std::to_string(12345);
    std::cout << "to_string: " << s1 << std::endl;
    
    // 字符串转整数(带错误处理)
    try {
        std::string s2 = "123abc";
        int num = std::stoi(s2);
        std::cout << "stoi: " << num << std::endl;
    } catch (const std::invalid_argument& e) {
        std::cout << "Invalid argument" << std::endl;
    } catch (const std::out_of_range& e) {
        std::cout << "Out of range" << std::endl;
    }
    
    // from_chars (C++17)
    std::string s3 = "999";
    int value;
    auto result = std::from_chars(s3.data(), s3.data() + s3.size(), value);
    if (result.ec == std::errc()) {
        std::cout << "from_chars: " << value << std::endl;
    }
    
    // C++20 format
    #if __cplusplus > 201703L
    std::string s4 = std::format("Hex: {:#x}", 255);
    std::cout << s4 << std::endl;  // "Hex: 0xff"
    #endif
    
    return 0;
}

六、常见陷阱

  1. stoi 不会跳过空白字符,但会抛出异常
  2. 进制问题:默认十进制,可通过base参数指定
  3. from_chars 不会跳过空白,效率最高但要求严格匹配
  4. 浮点数转换stod/to_string 可能产生精度问题

推荐:一般场景用 std::to_stringstd::stoi;性能关键场景用 std::from_chars 和自定义缓冲区的 to_chars

更多推荐