如何解决可以使用 C++20 范围就地修剪字符串吗?
受到可爱的 cppreference example of trim with C++20 的启发,我编写了以下代码(自从我的“问题“(我正在发明问题来学习 C++20)在使用 let data = fs.createReadStream('/home/insert/screen03.jpg');
let form = new FormData();
form.append('files',data,'test.jpg');
form.getLength((err,length) => {
if (err) { reject(err); }
let headers = Object.assign({ 'Content-Length': length,'Authorization': `Token b84db005a7fc1e5471a763aa42fcc5734b7bb22a` },form.getHeaders());
return axios.post(`http://192.168.88.252:8000/resources/`,form,{ headers: headers })
.then(res => console.log(res.data))
.catch(error => console.log(error.response.data))
});
arg 并返回 void
的原始代码中不存在。
std::string&
这里的问题是这不是就地,这意味着创建了新字符串。 我可以编写更丑陋的代码来执行此操作,并且我知道传统的 C++ 算法不知道容器的存在,但我想知道 C++20 是否有一些技巧使我能够以优雅的方式进行修剪,但也可以就地进行。
这也是我丑陋的就地修剪(不确定它是否可以正常工作,但想法是它进行了就地修剪):
std::string_view
编辑:最初这个问题声称 std::string
将是 UB,但 T.C.纠正我。但根据我对 C++23 草案的理解,分配仍然会导致创建临时字符串。
解决方法
也许是这样?
void trim(std::string& s) {
auto not_space = [](unsigned char c){ return !std::isspace(c); };
// erase the the spaces at the back first
// so we don't have to do extra work
s.erase(
std::ranges::find_if(s | std::views::reverse,not_space).base(),s.end());
// erase the spaces at the front
s.erase(
s.begin(),std::ranges::find_if(s,not_space));
}
,
带有任意迭代器的 assign
需要创建一个临时的(因为改变字符串可以以任意方式影响迭代器的结果,并且因为抛出迭代器操作必须保持原始字符串不变),但是每个主要实现都给定字符串自己的迭代器时是正确的。
所以我们可以解开 reverse_iterator
-ness 的两个级别:
auto view
= in
| std::views::drop_while(isspace)
| std::views::reverse
| std::views::drop_while(isspace)
| std::views::reverse;
in.assign(view.begin().base().base(),view.end().base().base());
(不过,我自己也会去找巴里的答案。)
此外,很少需要显式使用 views::all
;适配器会自动执行此操作。
是的,这是可能的:
void trim(std::string& s) {
auto view = s
| std::views::drop_while(isspace)
| std::views::reverse
| std::views::drop_while(isspace)
| std::views::reverse;
auto [in,out] = std::ranges::copy(view,s.begin());
s.erase(out,s.end());
}
demo。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。