C++ 字符格式化输出

文章目录

一、简介

这里使用std标准库简单实现一个字符格式化输出,方便后续的使用,它有点类似Qt中的QString操作。

二、实现代码

FMTString.hpp

cpp 复制代码
#pragma once

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <optional>
#include <random>
#include <type_traits>
#include <sstream>

namespace FMT 
{
    void formatStream(std::stringstream& stream, char const* text) {
        stream << text;
        return;
    }

    /// <summary>
    /// 在编译时检测某个类型T是否支持通过 operator<< 输出到流(如std::stringstream)
    /// </summary>
    /// <typeparam name="T"></typeparam>
    template <class T>
    class IsStreamable {
    private:
        template <class TT>
        static auto test(int)
            -> decltype(std::declval<std::stringstream&>() << std::declval<TT>(),
                std::true_type());

        template <class>
        static auto test(...)->std::false_type;

    public:
        static bool const value = decltype(test<T>(0))::value;
    };

    /// <summary>
    /// 将任意类型的参数通过流操作符 << 转换为字符串流(std::stringstream)的内容
    /// </summary>
    /// <typeparam name="T"></typeparam>
    template <class T>
    class ArgToStream {
    public:
        static void impl(std::stringstream& stream, T&& arg) {
            stream << std::forward<T>(arg);
        }
    };

    /// <summary>
    /// 将格式字符串 text 中的 {} 占位符依次替换为传入的参数 arg, args...,并将结果写入 std::stringstream 流中
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="...Args"></typeparam>
    /// <param name="stream"></param>
    /// <param name="text"></param>
    /// <param name="arg"></param>
    /// <param name="...args"></param>
    template <class T, typename... Args>
    void formatStream(std::stringstream& stream, char const* text, T&& arg,
        Args&&... args) {
        static_assert(IsStreamable<T>::value,
            "One of the args has no ostream overload!");
        for (; *text != '\0'; ++text) {
            if (*text == '{' && *(text + 1) == '}') {
                ArgToStream<T&&>::impl(stream, std::forward<T>(arg));
                formatStream(stream, text + 2, std::forward<Args>(args)...);
                return;
            }
            stream << *text;
        }
        stream << "\nFormat-Warning: There are " << sizeof...(Args) + 1
            << " args unused.";
        return;
    }

    template <class... Args>
    std::string formatString(char const* text, Args&&... args) {
        std::stringstream stream;
        formatStream(stream, text, std::forward<Args>(args)...);
        return stream.str();
    }
}

main.cpp

cpp 复制代码
// 标准文件
#include <iostream>
#include <string>

#include "FMTString.hpp"

int main(int, char** argv)
{
    std::string msg = FMT::formatString("Hello, {}! You have {} new messages.", "Alice", 5);
    std::cout << "Output:" << msg << std::endl;

    system("pause");
    return 0;
}

三、实现效果

相关推荐
方传旺9 分钟前
C++17 std::optional 深拷贝 vs 引用:unordered_map 查询大对象性能对比
c++
Dontla24 分钟前
Makefile介绍(Makefile教程)(C/C++编译构建、自动化构建工具)
c语言·c++·自动化
何妨重温wdys1 小时前
矩阵链相乘的最少乘法次数(动态规划解法)
c++·算法·矩阵·动态规划
重启的码农1 小时前
ggml 介绍 (6) 后端 (ggml_backend)
c++·人工智能·神经网络
重启的码农1 小时前
ggml介绍 (7)后端缓冲区 (ggml_backend_buffer)
c++·人工智能·神经网络
雨落倾城夏未凉1 小时前
5.通过拷贝构造函数复制一个对象,假如对象的成员中有个指针类型的变量,如何避免拷贝出来的副本中的该成员之下行同一块内存(等价于默认拷贝构造函数有没有缺点)
c++·后端
雨落倾城夏未凉1 小时前
4.深拷贝VS浅拷贝
c++·后端
tanyongxi662 小时前
C++ 特殊类设计与单例模式解析
java·开发语言·数据结构·c++·算法·单例模式
fqbqrr2 小时前
2508C++,支持rdma通信的高性能rpc库
c++·rpc
liulilittle3 小时前
BFS寻路算法解析与实现
开发语言·c++·算法·宽度优先·寻路算法·寻路