我想区分数组的结尾和其余元素(在for循环中),但是大多数示例在循环外部初始化变量,我认为这会使循环变得混乱。我实现的最短的例子是通过查看基于范围的for循环中的指针地址:
for(auto& x : arr){
cout << x;
if(&x != &*end(arr)-1)
cout << ", ";
}
这不需要额外的变量,但我不能100%确定在C ++中使用指针的含义。
一个更多(或更少?)可读的例子,我在for-statement中初始化一个变量,看起来非常直观(编辑不提供对函数的可移植性):
for(int i{0}, len{sizeof(arr)/sizeof(*arr)}; i<l; i++){
cout << arr[i];
if(i!=len-1)
cout << ", ";
}
为什么不这样做呢?
bool not_first_item = false;
for(auto x : arr){
if (not_first_item) {
cout << ", ";
not_first_item = true;
}
cout << x;
}
除了第一个项目之外,它将在每个项目之前打印一个逗号。它将获得您需要的结果,而无需使用复杂的指针。
如果只有一个指向数组中元素的指针,则没有可移植的方法来检测数组中该元素的位置。
备择方案;最好的第一:
std::vector
。它具有与普通旧数组类似的语义,并具有携带大小的好处。size_t
类型将数组的大小作为附加参数传递。请注意,使用&x
是没有意义的,因为x
是一个值副本。考虑auto& x
而不是?
这可能有所帮助
l=sizeof(arr)
for(int i{0}; i<l-1; i++){
cout << arr[i];
cout << ", ";
}
cout << arr[sizeof(arr)];
要么
for(int i{0}; i<sizeof(arr)-1; i++){
cout << arr[i];
cout << ", ";
}
cout << arr[sizeof(arr)];
没有额外的条件。如果显示是主要意图
我喜欢的简洁方式,没有额外的分支:
const char* sep = "";
for (const auto& x : arr) {
std::cout << sep << x;
sep = ", ";
}
是的,它使用额外的变量。
作为一般规则,您不应丢弃所需的信息。当您使用基于范围的for循环时,您将抽象出容器中元素的位置(实际上是容器的形式)。因此,它不是最适合这项工作的工具。您可以使用索引或迭代器执行此操作,因为这些信息包含足够的信息,以告知您迭代的元素是否是最后一个元素。
标准库提供了两个有用的函数begin
和end
,它们可以调用STL容器的成员函数begin
和end
,也可以指向C样式数组的第一个和过去元素的指针。由于检查结束条件的方式,除了前向迭代器之外,您不需要任何其他内容。
assert(std::begin(arr) != std::end(arr));
for (auto it = std::begin(arr); it + 1 != std::end(arr); ++it) {
std::cout << *it << ", ";
}
std::cout << *(std::end(arr) - 1) << '\n';
如果你知道你永远不会尝试打印空容器,上面的代码就可以了。否则,您需要额外的if
声明来检查。请注意,即使您有一个随机访问迭代器并使用条件it < std::end(arr) - 1
,您可能会认为它对于空数组也没问题,但它是未定义的行为,并且在启用优化时可能会导致一些意外错误。
不是100%肯定我在寻找什么,但我认为真正的答案可能是检查像@ed_heel提议的起始项目,但我真的只需要改变我在基于范围的for循环中检查的内容它更整洁:
for(auto &x : arr)
{
cout << (&x == arr ? "" : ", ") << x;
}
因为arr是一个数组(伪装的a.k.a.指针)。