C/C++使用fmt库实现格式化字符串

 更新时间:2023年12月25日 14:35:43   作者:liulilittle  
fmt库是一个高效、易用的C++格式化库,可以帮助我们方便地进行字符串格式化、输出、日志记录等操作,下面我们就来学习一下fmt格式化字符串的具体操作吧

实现的目的;提高 C/C++ 编译速度,fmt 库模板嵌套过多编译速度非常慢,且编译后程序体积也过大,函数步入的栈帧过多!

只支持格式;{}

不支持格式;{:02x}

class fmt
{
public:
    template <typename S, typename ...T>
    static std::string              format(const S& fmt, T ... args) noexcept
    {
        std::string str;
        if constexpr (std::is_same<S, std::string>::value)
        {
            str = fmt;
        }
        else if constexpr (std::is_same<S, std::string_view>::value)
        {
            str = std::string(fmt.data(), fmt.size());
        }
        else
        {
            str = fmt;
        }
 
        (..., format_string(str, args));
        return str;
    }
 
    template <typename OutputIt, typename ...T>
    static void                     format_to(OutputIt&& out, const std::string& fmt, T ... args)
    {
        std::string result = format(fmt, std::forward<T&&>(args)...);
        for (char ch : result)
        {
            *out = ch;
        }
    }
 
private:
    template <typename T>
    static std::string              to_string(const T& value) noexcept
    {
        if constexpr (std::is_same<T, bool>::value)
        {
            return value ? "true" : "false";
        }
        else if constexpr (std::is_pointer<T>::value)
        {
            using DECAY_T = typename std::decay<T>::type;
 
            if constexpr (std::is_same<char*, DECAY_T>::value || std::is_same<const char*, DECAY_T>::value)
            {
                return value ? value : "";
            }
            else 
            {
                if (value)
                {
                    char buf[sizeof(value) << 2];
                    snprintf(buf, sizeof(buf), "%p", reinterpret_cast<const void*>(value));
                    return buf;
                }
                return "null";
            }
        }
        else if constexpr (std::is_same<T, std::string>::value)
        {
            return value;
        }
        else if constexpr (std::is_same<T, std::string_view>::value)
        {
            return std::string(value.data(), value.size());
        }
        else
        {
            return std::to_string(value);
        }
    }
 
    template <typename T>
    static std::string              to_string(const std::shared_ptr<T>& value) noexcept
    {
        return fmt::to_string(value.get());
    }
 
    template <typename T>
    static void                     format_string(std::string& out, const T& value) noexcept
    {
        replace_string(out, "{}"sv, fmt::to_string(value));
    }
 
public:
    static bool                     replace_string(std::string& str, const std::string_view& old_string, const std::string_view& new_string) noexcept;
};
 
inline bool fmt::replace_string(std::string& str, const std::string_view& old_string, const std::string_view& new_string) noexcept
{
    size_t pos = str.find(old_string);
    if (pos == std::string::npos)
    {
        return false;
    }
 
    str.replace(pos, old_string.length(), new_string);
    return true;
}

方法补充

除了上文的方法,小编还为大家整理了其他C++格式化字符串的方法,希望对大家有所帮助

1.使用C++中的字符串流(stringstream)

例如:

#include <sstream>
std::stringstream ss;
int num = 42;
const char* str = "hello";
ss << "Num: " << num << ", str: " << str;
std::string result = ss.str();

上述代码中,我们使用字符串流将数字和字符串插入到字符串中,得到了最终的格式化结果。

需要注意的是,当处理浮点数时,可能会出现精度误差的问题,可以使用std::setprecision函数来指定小数点后的位数。

示例说明

下面是一个例子,展示了使用字符串流格式化浮点数的方法:

#include <sstream>
#include <iomanip>
std::stringstream ss;
double num = 3.14159265358979323846;
ss << "The value of pi is approximately " << std::setprecision(6) << std::fixed << num;
std::string result = ss.str();

上述代码中,我们使用字符串流将浮点数插入到字符串中,并设置小数点后6位的精度,输出结果为:

The value of pi is approximately 3.141593.

2.使用format库

format库是C++11格式化字符串的一种解决方案,它的设计目标是提供简单、便捷的格式化语法,并且不需要调用大量的函数来实现字符串的格式化。

format库可以被看作是一个功能强大的printf的替代品。在使用上它更加灵活,更加安全,而且能够提供更加友好的错误提示。

format库的使用方式和Python的字符串格式化方式非常相似,适合需要频繁使用字符串格式化的场景。

具体用法

#include <fmt/format.h>
#include <iostream>

int main(){
    std::cout << fmt::format("{} {} {}!\n", "Hello", "World", 123);
    std::cout << fmt::format("{2} {1} {0}!\n", "Hello", "World", 123);
    std::cout << fmt::format("{0:+} {0:-} {0:#}\n", 123);
    std::cout << fmt::format("{0:.3f} {0:7.3f}\n", 3.1415926535);
    std::cout << fmt::format("{{ }}\n");
    return 0;
}

到此这篇关于C/C++使用fmt库实现格式化字符串的文章就介绍到这了,更多相关C++格式化字符串内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言中的各种文件读写方法小结

    C语言中的各种文件读写方法小结

    这篇文章主要介绍了C语言中的各种文件读写方法小结,是C语言入门学习中的基础知识,需要的朋友可以参考下
    2015-07-07
  • C++实现特殊矩阵的压缩存储算法

    C++实现特殊矩阵的压缩存储算法

    在实际存储时,会发现矩阵中有许多值相同的数据或有许多零数据,且分布呈现出一定的规律,称这类型的矩阵为特殊矩阵。本文将利用C++实现特殊矩阵的压缩存储,感兴趣的可以了解一下
    2022-08-08
  • 循环队列详解及队列的顺序表示和实现

    循环队列详解及队列的顺序表示和实现

    这篇文章主要介绍了循环队列详解及队列的顺序表示和实现的相关资料,需要的朋友可以参考下
    2016-12-12
  • C++ list容器merge算法的使用以及注意事项

    C++ list容器merge算法的使用以及注意事项

    这篇文章主要介绍了C++ list容器merge算法的使用以及注意事项,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • 介绍C语言中tolower函数的实例

    介绍C语言中tolower函数的实例

    这篇文章主要介绍了介绍C语言中tolower函数的实例,本文列出了该函数的头文件,功能说明等,以及如何使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C语言之qsort函数详解

    C语言之qsort函数详解

    这篇文章主要介绍了C语言中qsort函数的用法实例详解的相关资料,希望通过本文能帮助到大家,让大家理解掌握这部分内容,需要的朋友可以参考下
    2021-08-08
  • Linux C 时间函数应用

    Linux C 时间函数应用

    本文是关于Linux C时间函数 time_t struct tm 进行了详细的分析介绍并有应用实例,希望能帮到有需要的同学
    2016-07-07
  • C语言中全局数组和局部数组的问题

    C语言中全局数组和局部数组的问题

    今天同学遇到一个在C语言中全局数组和局部数组的问题,卡了许久,我也没有第一时间看出问题,现在把问题梳理一下,并给出解决方案,需要的朋友可以参考下
    2012-12-12
  • 简要介绍C++编程中的友元函数和友元类

    简要介绍C++编程中的友元函数和友元类

    这篇文章主要介绍了C++编程中的友元函数和友元类,属于较为冷僻的知识,在实际开发中较少使用,需要的朋友可以参考下
    2015-09-09
  • C++ Date类的具体使用(构建,重载等)

    C++ Date类的具体使用(构建,重载等)

    本文主要介绍了C++ Date类的具体使用(构建,重载等),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07

最新评论