ein*_*ica 76 c++ idioms separator c++11
每个人都会遇到这个问题:
for(const auto& item : items) {
cout << item << separator;
}
Run Code Online (Sandbox Code Playgroud)
...而且你得到了一个你不想要的额外分隔符.有时候它不是打印,而是执行一些其他动作,但是相同类型的连续动作需要一些分隔符动作 - 但最后一个动作不需要.
现在,如果你使用old-school for循环和数组,你会这样做
for(int i = 0; i < num_items; i++)
cout << items[i];
if (i < num_items - 1) { cout << separator; }
}
Run Code Online (Sandbox Code Playgroud)
(或者你可以特别说明循环中的最后一项.)如果你有任何承认非破坏性迭代器的东西,即使你不知道它的大小,你可以这样做:
for(auto it = items.cbegin(); it != items.cend(); it++) {
cout << *it;
if (std::next(it) != items.cend()) { cout << separator; }
}
Run Code Online (Sandbox Code Playgroud)
我不喜欢最后两个的美学,并喜欢一系列的循环.我可以获得与后两个相同的效果,但使用更多漂亮的C++ 11ish结构吗?
for(const auto& item : items) {
cout << item;
} and_between {
cout << separator;
}
Run Code Online (Sandbox Code Playgroud)
Jar*_*d42 74
我的方式(没有额外的分支)是:
const auto separator = "WhatYouWantHere";
const auto* sep = "";
for(const auto& item : items) {
std::cout << sep << item;
sep = separator;
}
Run Code Online (Sandbox Code Playgroud)
Ben*_*igt 24
从迭代中排除结束元素是Ranges提案旨在简化的一种方式.(请注意,有更好的方法可以解决字符串连接的特定任务,从迭代中断开元素只会创建更多特殊情况,例如当集合已经为空时.)
当我们等待标准化的Ranges范例时,我们可以使用现有的ranged-for一个小帮助类来完成它.
template<typename T> struct trim_last
{
T& inner;
friend auto begin( const trim_last& outer )
{ using std::begin;
return begin(outer.inner); }
friend auto end( const trim_last& outer )
{ using std::end;
auto e = end(outer.inner); if(e != begin(outer)) --e; return e; }
};
template<typename T> trim_last<T> skip_last( T& inner ) { return { inner }; }
Run Code Online (Sandbox Code Playgroud)
现在你可以写了
for(const auto& item : skip_last(items)) {
cout << item << separator;
}
Run Code Online (Sandbox Code Playgroud)
演示:http://rextester.com/MFH77611
对于skip_last
使用ranged-for的方法,需要一个双向迭代器,类似地,skip_first
它具有一个Forward迭代器就足够了.
Dan*_*our 24
你知道Duff的设备吗?
int main() {
int const items[] = {21, 42, 63};
int const * item = items;
int const * const end = items + sizeof(items) / sizeof(items[0]);
// the device:
switch (1) {
case 0: do { cout << ", ";
default: cout << *item; ++item; } while (item != end);
}
cout << endl << "I'm so sorry" << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
希望我没有毁掉每个人的一天.如果您不想要,则永远不要使用它.
(嘟))我很抱歉......
处理空容器的设备(范围):
template<typename Iterator, typename Fn1, typename Fn2>
void for_the_device(Iterator from, Iterator to, Fn1 always, Fn2 butFirst) {
switch ((from == to) ? 1 : 2) {
case 0:
do {
butFirst(*from);
case 2:
always(*from); ++from;
} while (from != to);
default: // reached directly when from == to
break;
}
}
Run Code Online (Sandbox Code Playgroud)
现场测试:
int main() {
int const items[] = {21, 42, 63};
int const * const end = items + sizeof(items) / sizeof(items[0]);
for_the_device(items, end,
[](auto const & i) { cout << i;},
[](auto const & i) { cout << ", ";});
cout << endl << "I'm (still) so sorry" << endl;
// Now on an empty range
for_the_device(end, end,
[](auto const & i) { cout << i;},
[](auto const & i) { cout << ", ";});
cout << "Incredibly sorry." << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Jam*_*son 13
我不知道有什么特别的习语.但是,我更喜欢第一种特殊情况,然后对剩余的项目执行操作.
#include <iostream>
#include <vector>
int main()
{
std::vector<int> values = { 1, 2, 3, 4, 5 };
std::cout << "\"";
if (!values.empty())
{
std::cout << values[0];
for (size_t i = 1; i < values.size(); ++i)
{
std::cout << ", " << values[i];
}
}
std::cout << "\"\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出: "1, 2, 3, 4, 5"
Mat*_*lia 13
通常我会这样做:
bool first=true;
for(const auto& item : items) {
if(!first) cout<<separator;
first = false;
cout << item;
}
Run Code Online (Sandbox Code Playgroud)
我喜欢简单的控制结构.
if (first == last) return;
while (true) {
std::cout << *first;
++first;
if (first == last) break;
std::cout << separator;
}
Run Code Online (Sandbox Code Playgroud)
根据您的喜好,您可以将增量和测试放在一行中:
...
while (true) {
std::cout << *first;
if (++first == last) break;
std::cout << separator;
}
Run Code Online (Sandbox Code Playgroud)
我不知道你可以在某个地方找到一个特殊情况...例如,Boost的String Algorithms Library有一个连接算法.如果你看一下它的实现,你会看到第一个项目的特殊情况(没有前进的分隔符),然后在每个后续元素之前添加一个分隔符.
您可以定义一个函数for_each_and_join,它将两个仿函数作为参数.第一个仿函数可以处理每个元素,第二个函数与每对相邻元素一起使用:
#include <iostream>
#include <vector>
template <typename Iter, typename FEach, typename FJoin>
void for_each_and_join(Iter iter, Iter end, FEach&& feach, FJoin&& fjoin)
{
if (iter == end)
return;
while (true) {
feach(*iter);
Iter curr = iter;
if (++iter == end)
return;
fjoin(*curr, *iter);
}
}
int main() {
std::vector<int> values = { 1, 2, 3, 4, 5 };
for_each_and_join(values.begin(), values.end()
, [](auto v) { std::cout << v; }
, [](auto, auto) { std::cout << ","; }
);
}
Run Code Online (Sandbox Code Playgroud)
int a[3] = {1,2,3};
int size = 3;
int i = 0;
do {
std::cout << a[i];
} while (++i < size && std::cout << ", ");
Run Code Online (Sandbox Code Playgroud)
输出:
1, 2, 3
Run Code Online (Sandbox Code Playgroud)
目标是使用&&
评估方式.如果第一个条件为真,则计算第二个条件.如果不是,则跳过第二个条件.
归档时间: |
|
查看次数: |
6697 次 |
最近记录: |