You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用spdlog打印std::to_string生成的矩阵时如何添加行首偏移和前缀

实现方案

以下是完全基于现有spdlog工具栈的轻量实现,不需要引入额外依赖,可根据场景灵活选择:

方案1:多行内容预处理函数(最轻量,无侵入)

先封装通用的字符串处理工具,对转换后的矩阵/向量多行字符串做格式化处理,调用时直接传入处理后的结果即可,不需要修改原有日志配置。

#include <string>
#include <sstream>

/**
 * @param raw_str 原始多行字符串
 * @param indent 后续行缩进长度,填日志前缀的总字符数即可对齐首行
 * @param line_prefix 可选行前缀字符,传'\0'则不添加
 * @return 格式化后的多行字符串
 */
std::string format_multiline_log(const std::string& raw_str, int indent = 0, char line_prefix = '\0') {
    std::istringstream iss(raw_str);
    std::ostringstream oss;
    std::string line;
    bool first_line = true;
    std::string indent_str(indent, ' ');

    while (std::getline(iss, line)) {
        if (!first_line) {
            oss << '\n' << indent_str;
        }
        if (line_prefix != '\0') {
            oss << line_prefix << ' ';
        }
        oss << line;
        first_line = false;
    }
    return oss.str();
}

调用示例:

// 假设你的日志前缀总长度为22(日期+级别等字段总字符数)
std::string raw_matrix = your_matrix_to_string_func();
spdlog::info("Matrix output:\n{}", format_multiline_log(raw_matrix, 22, '|'));

方案2:自定义spdlog formatter(全局生效,无需每次手动处理)

如果需要所有多行日志都自动对齐,可自定义spdlog格式化器,全局生效不需要修改业务打印代码:

#include "spdlog/spdlog.h"
#include "spdlog/formatter.h"

class aligned_multiline_formatter : public spdlog::formatter {
public:
    aligned_multiline_formatter(int prefix_len, char line_prefix = '\0') 
        : prefix_len_(prefix_len), line_prefix_(line_prefix) {}

    void format(const spdlog::details::log_msg& msg, spdlog::memory_buf_t& dest) override {
        // 按原有日志pattern格式化前缀,此处替换为你自己的前缀格式化逻辑即可
        std::string prefix = get_origin_log_prefix(msg);
        std::string content(msg.payload.data(), msg.payload.size());
        std::istringstream iss(content);
        std::ostringstream oss;
        std::string line;
        bool first_line = true;
        std::string indent(prefix_len_, ' ');

        while (std::getline(iss, line)) {
            if (!first_line) {
                oss << '\n' << indent;
            }
            if (line_prefix_ != '\0') {
                oss << line_prefix_ << ' ';
            }
            oss << line;
            first_line = false;
        }

        std::string final_log = prefix + oss.str() + '\n';
        dest.append(final_log.data(), final_log.data() + final_log.size());
    }

    std::unique_ptr<formatter> clone() const override {
        return std::make_unique<aligned_multiline_formatter>(prefix_len_, line_prefix_);
    }
private:
    int prefix_len_;
    char line_prefix_;

    std::string get_origin_log_prefix(const spdlog::details::log_msg& msg) {
        // 示例:如果原有pattern是"[%Y-%m-%d %H:%M:%S] [%l] ",此处返回对应格式化后的前缀即可
        return "[2024-05-20 14:30:00] [info] ";
    }
};

// 注册到logger即可全局生效
auto logger = spdlog::stdout_color_mt("console");
logger->set_formatter(std::make_unique<aligned_multiline_formatter>(22, '|'));

方案3:配合矩阵库自带格式化能力

如果项目中使用Eigen等线性代数库,可直接用库自带的IO配置实现自定义前缀,再配合方案1的缩进逻辑即可:

#include <Eigen/Dense>
Eigen::Matrix3f mat;
mat << 1,2,3,4,5,6,7,8,9;
// 配置每行开头加| 前缀
Eigen::IOFormat mat_fmt(4, 0, ", ", "\n", "| ", "| ");
std::string raw_mat_str = [&](){
    std::ostringstream oss;
    oss << mat.format(mat_fmt);
    return oss.str();
}();
spdlog::info("Matrix:\n{}", format_multiline_log(raw_mat_str, 22));
注意事项
  • 如果日志前缀是动态长度(比如不同级别名称长度不同),可以在格式化函数中动态计算当前日志前缀的实际长度,再对应补缩进
  • 仅需要矩阵/向量类特殊格式化的场景优先选方案1,侵入性最低,和现有代码完全兼容
  • 行前缀可根据日志级别设置不同字符,比如debug用>,error用!,进一步提升可读性

内容的提问来源于stack exchange,提问作者Alejandro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 09:27:03