如何去除C++多行raw string literals中的前导空格?
解决C++多行原始字符串字面量前导空格问题
你不想把字符串左移到代码最左侧破坏缩进格式,但又要移除输出中的前导空格,这里有几种实用方案:
方案一:编译时移除固定前缀空格(C++20+)
写一个constexpr函数,在编译阶段就处理掉每一行的固定数量前导空格,不影响运行效率,同时保持代码缩进:
#include <string> #include <print> #include <algorithm> #include <ranges> constexpr std::string_view trim_lines_prefix(std::string_view sv, std::size_t prefix_len) { std::string result; bool skip_first = true; for (auto line : sv | std::views::split('\n')) { if (skip_first) { skip_first = false; continue; // 跳过原始字符串开头的空行 } // 移除对应长度的前导空格,长度不足则保留原内容 if (line.size() >= prefix_len) { result += std::string_view(line.begin() + prefix_len, line.end()); } else { result += std::string_view(line.begin(), line.end()); } result += '\n'; } if (!result.empty()) result.pop_back(); // 去掉最后多余的换行 return std::string_view(result); } int main() { constexpr auto preamble_raw = R"( <?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml"> <head> <meta name="Author" content="Some One" /> <title>Title Of Page</title> </head> <body style=""> )"; // 这里的8是原始字符串每行的前导空格数,根据实际缩进调整 constexpr auto preamble = trim_lines_prefix(preamble_raw, 8); std::println("{}", preamble); return 0; }
方案二:预处理器宏自动适配缩进(兼容C++11+)
用宏自动识别第一行有效内容的前导空格数,批量移除所有行的对应空格,无需手动指定长度:
#include <string> #include <print> #define RAW_STR(...) #__VA_ARGS__ #define TRIMMED_RAW_STR(...) \ []() { \ std::string s = RAW_STR(__VA_ARGS__); \ size_t prefix_len = s.find_first_not_of("\n \t"); \ if (prefix_len == std::string::npos) return s; \ size_t line_pos = 0; \ while ((line_pos = s.find('\n', line_pos)) != std::string::npos) { \ ++line_pos; \ // 如果当前行开头有对应数量的空格,就移除 if (s.substr(line_pos, prefix_len) == std::string(prefix_len, ' ')) { \ s.erase(line_pos, prefix_len); \ } \ } \ // 去掉开头的空白行和空格 s.erase(0, s.find_first_not_of("\n \t")); \ return s; \ }() int main() { auto preamble = TRIMMED_RAW_STR( <?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml"> <head> <meta name="Author" content="Some One" /> <title>Title Of Page</title> </head> <body style=""> ); std::println("{}", preamble); return 0; }
这个宏会自动处理缩进,不管你在类方法还是嵌套命名空间里,代码的缩进格式都能保持原样。
方案三:C++23范围工具简化处理
如果你的项目已经用C++23,用std::views可以写出更简洁的代码:
#include <string> #include <print> #include <ranges> #include <string> int main() { constexpr std::string_view preamble_raw = R"( <?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="https://www.w3.org/1999/xhtml"> <head> <meta name="Author" content="Some One" /> <title>Title Of Page</title> </head> <body style=""> )"; auto trimmed = preamble_raw | std::views::drop(1) // 跳过开头的空行 | std::views::transform([](auto line) { // 每行去掉前8个空格,根据实际缩进调整 return std::string_view(line).substr(8); }) | std::views::join_with('\n'); std::println("{}", std::string(trimmed)); return 0; }
内容的提问来源于stack exchange,提问作者Penny Dreudter
相关产品推荐
相关产品推荐

