字符串数值转换

字符串 和 数值 之间的相互转换,有两种方式。一种是使用高级函数(在<string>中定义),一种是使用低级函数(在<charconv>中定义)。

高级数值转换(High-Level Numeric Conversions)

代码如下:

#include <iostream>
#include <string>

int main() {
    {
        // 数值 转换为 字符串
        // std::to_string()

        int i {345};
        std::string s1{std::to_string(i)};

        double d {3.14};
        std::string s2{std::to_string(d)};

        long double ld {3.14L};
        std::string s3{std::to_string(ld)};

        std::cout << s1 << " " << s2 << " " << s3 << std::endl;
    }

    {
        // 字符串 转换为 数值
        // 函数命名规则:s(字符串) to 数值类型简写
        /*
         * i, int, stoi()
         * l, long, stol()
         * ul, unsigned long, stoul()
         * ll, long long, stoll()
         * ull, unsigned long long, stoull()
         * f, float, stof()
         * d, double, stod()
         * ld, long double, stold()
         */
        const std::string toParse {"    123USD"};

        size_t index{0};  // 用于存放未能转换的字符中第一个字符的索引
        int value {std::stoi(toParse, &index)};

        std::cout << "转换结果:" << value << std::endl;
        std::cout << "第一个未能转换的字符:" << toParse[index] << std::endl;
        std::cout << "未能转换的字符:" << toParse.substr(index) << std::endl;
    }

    return 0;
}

低级数值转换(Low-Level Numeric Conversions)

什么是“完美往返”(perfect round-tripping)?将数值转换为字符串,然后将结果字符串再次转换为数值,所得到的结果与原始数值相同。

代码如下:

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

int main() {
    {
        // 整数数值 转换为 字符串
        // std::to_chars()
        /*
        返回类型为:
        struct to_chars_result {
            char* ptr;
            errc ec;
        };
        */

        int i {12345};

        // 缓冲区,大小为50,用空格初始化
        const size_t BufferSize {50};
        std::string out(BufferSize, ' ');  // 一个由 BufferSize 个空格组成的字符串

        // 普通写法
        auto result {std::to_chars(out.data(), out.data() + out.size(), i)};
        if (result.ec == std::errc{}) {  // 转换成功
            std::cout << out << std::endl;
        }

        // 使用 结构化绑定(structured bindings) 的写法
        auto [ptr, error] {std::to_chars(out.data(), out.data() + out.size(), i)};
        if (error == std::errc{}) {  // 转换成功
            std::cout << out << std::endl;
        }
    }

    {
        // 浮点数数值 转换为 字符串
        // std::to_chars()

        double value {0.314};

        // 缓冲区,大小为50,用空格初始化
        const size_t BufferSize {50};
        std::string out(BufferSize, ' ');  // 一个由 BufferSize 个空格组成的字符串

        auto [ptr, error] {std::to_chars(out.data(), out.data() + out.size(), value)};
        if (error == std::errc{}) {  // 转换成功
            std::cout << out << std::endl;
        }
    }

    {
        // 字符串 转换为 数值
        // std::from_chars()
        /*
        返回类型为:
        struct from_chars_result {
            const char* ptr;
            errc ec;
        };
        */

        const std::string toParse {"    123USD"};
        int result;

        // 由于 std::from_chars() 不会跳过左侧空格,所以在转换前应当先去除空格
        const std::string midValue {toParse.substr(4)};  // 只是演示,所以就只是手动去除了字符串左侧空格
        auto [ptr, error] {std::from_chars(midValue.data(), midValue.data() + midValue.size(), result)};
        if (error == std::errc{}) {  // 转换成功
            std::cout << result << std::endl;
        }
    }

    {
        // 完美往返
        // double 数值 转换为 字符串,然后从结果字符串转换为 double 数值,所得结果和原始数值相同。
        double value {0.314};

        // 缓冲区,大小为50,用空格初始化
        const size_t BufferSize {50};
        std::string out(BufferSize, ' ');  // 一个由 BufferSize 个空格组成的字符串

        auto [ptr1, error1] {std::to_chars(out.data(), out.data() + out.size(), value)};
        if (error1 == std::errc{}) {  // 转换成功
            std::cout << "double -> 字符串 成功:" << out << std::endl;
        }

        double resultValue;
        auto [ptr2, error2] {std::from_chars(out.data(), out.data() + out.size(), resultValue)};
        if (error2 == std::errc{}) {  // 转换成功
            std::cout << "字符串 -> double 成功:" << resultValue << std::endl;
        }

        if (resultValue == value) {
            std::cout << "完美往返" << std::endl;
        }
    }

    return 0;
}

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注