英文:
Can I repeat a std::string_view without copying when printing indentation?
问题
#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 */);
}
};
英文:
I have a simple scene in C++ code.
I want to get a long string containing some repeated std::string_view
; is there a way to achieve this without copying the string?
#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 */);
}
};
答案1
得分: 3
C风格解决方案
std::printf
允许您动态指定字段宽度。例如:
#include <cstdio>
int main() {
int indent_length = 4;
int indent_depth = 3;
// 注意:将""作为%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;
}
然而,如果缩进不是不同字符的混合,
我们可以使用与上面相同的方法来避免这个循环:
void log(std::string_view msg) {
std::cout << std::setw(indent_length * level) << "" << msg;
}
如果您坚决要使用std::printf
,我们仍然可以这样做:
// 如果msg始终以null结尾
std::printf("%s", msg.data());
// 否则
std::printf("%.*s", int(msg.length()), msg.data());
您的indent
字符串可以以完全相同的方式打印。
英文:
C-Style Solution
std::printf
allows you to dynamically specify the field width. For example:
#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, "");
}
This will output:
hi!
We can use this trick because indentation always consist of one character, so we don't really have to repeat a full std::string_view
.
Obviously, this wouldn't work if you wanted indentation that is a mixture of multiple characters, but that would be highly unusual.
Old-School C++ Solution
However, that is a very C-style solution, and you could just use a loop to avoid copying:
void log(std::string_view msg) {
for (int i = 0; i < level; ++i) {
std::cout << indent;
}
std::cout << msg;
}
However, if the indent is not a mixture of different characters,
we can do a similar trick using std::cout
as above to avoid this loop:
void log(std::string_view msg) {
std::cout << std::setw(indent_length * level) << "" << msg;
}
If you absolutely insist on using std::printf
, we can still do:
// if msg is always null-terminated
std::printf("%s", msg.data());
// otherwise
std::printf("%.*s", int(msg.length()), msg.data());
Your indent
string can be printed exactly the same way.
答案2
得分: 0
答案是不,但 std::views::repeat
或 std::ranges::repeat_view
可以帮助您编写更简洁和更可读的代码。
作为替代,如果您事先知道最大缩进量,您可以初始化一个 std::array
的 string_view
,其维度为最大缩进量的数量,其中每个 string_view
都具有模式的递增重复。
英文:
The Answer to you question is NO,
but std::views::repeat
or std::ranges::repeat_view
can help you write more concise and more readable code.
In alternative, if you know a priori the max indentation, you could initialize a std::array
of string_view
, where the dimension is the number of max indentation, where each string_view
, have incremental repetion of the pattern.
答案3
得分: 0
I would try to do the longest possible ident and then extract subview from it:
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);
}
But I think this is not what you actually need.
英文:
I would try do longest possible ident and then extract subview form it:
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);
}
But I think this is not what you actually need.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论