c++ 我可以在打印缩进时重复std::string_view而不复制吗?

cunj1qz1  于 2023-07-01  发布在  其他
关注(0)|答案(3)|浏览(142)

我有一个简单的C++代码。我想得到一个长字符串,其中包含一些重复的std::string_view;有没有一种方法可以做到这一点,而不复制字符串?

#include <cstdio>
#include <string_view>

struct Logger {
    static inline constexpr std::string_view indent = "    ";
    static inline int level = 0;

    Logger() {
        level++;
    }

    // ...
    
    void log(const std::string &msg) {
        std::printf(/* repeat indent 'level' times */);
    }
};
fhg3lkii

fhg3lkii1#

C风格解决方案

std::printf允许您动态指定字段宽度。例如:

#include <cstdio>

int main() {
    int indent_length = 4;
    int indent_depth = 3;

    // note: "" is passed as an argument for %s
    std::printf("%*shi!", indent_length * indent_depth, "");
}

这将输出:

hi!

我们可以使用这个技巧,因为缩进总是由一个字符组成,所以我们不必重复完整的std::string_view。显然,如果您希望缩进是多个字符的混合,这将不起作用,但这将是非常不寻常的。

老派C++解决方案

然而,这是一个非常C风格的解决方案,你可以使用一个循环来避免复制:

void log(std::string_view msg) {
    for (int i = 0; i < level; ++i) {
        std::cout << indent;
    }
    std::cout << msg;
}

但是,如果缩进不是不同字符的混合,我们可以使用上面的std::cout来避免这种循环:

void log(std::string_view msg) {
    std::cout << std::setw(indent_length * level) << "" << msg;
}

如果你坚持使用std::printf,我们仍然可以这样做:

// if msg is always null-terminated
std::printf("%s", msg.data());

// otherwise
std::printf("%.*s", int(msg.length()), msg.data());

你的indent字符串可以用同样的方式打印出来。

uhry853o

uhry853o2#

你的问题的答案是
但是std::views::repeatstd::ranges::repeat_view可以帮助您编写更简洁、更易读的代码。
或者,如果你事先知道最大缩进,你可以初始化string_viewstd::array,其中维度是最大缩进的数量,其中每个string_view都有模式的增量重复。

liwlm1x9

liwlm1x93#

我会尝试做尽可能长的识别,然后提取子视图形式:

using namespace std::string_view_literals;

constexpr auto MaxIndentView = "                                            "sv;

constexpr std::string_view indentView(size_t n)
{
    if (n * 4 > MaxIndentView.size()) {
        throw std::invalid_argument{"Max indentation reached"};
    }
    return MaxIndentView.substr(0, n * 4);
}

但我认为这不是你实际需要的。

相关问题