我想区分数组的结尾和其余元素(在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 << ", ";
}
答案 0 :(得分:3)
为什么不这样做?
bool not_first_item = false;
for(auto x : arr){
if (not_first_item) {
cout << ", ";
not_first_item = true;
}
cout << x;
}
除了第一个项目之外,它将在每个项目之前打印一个逗号。它将获得您需要的结果,而无需使用复杂的指针。
答案 1 :(得分:1)
如果你只拥有一个指向数组中元素的指针,那么没有可移植的检测数组中该元素的位置。
替代品;最好的第一个:
使用std::vector
。它具有与普通旧数组类似的语义,并具有携带大小的好处。
将数组的大小作为附加参数传递,使用size_t
类型。
使用魔术值表示数组的结尾。
请注意,使用&x
毫无意义,因为x
是值副本。请考虑使用auto& x
?
答案 2 :(得分:1)
这可能会有所帮助
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)];
没有额外的条件。 如果显示是主要意图
答案 3 :(得分:1)
我喜欢的简洁方式,没有额外的分支:
const char* sep = "";
for (const auto& x : arr) {
std::cout << sep << x;
sep = ", ";
}
是的,它使用了额外的变量。
答案 4 :(得分:0)
作为一般规则,您不应丢弃所需的信息。当您使用基于范围的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
,您也可能会认为即使对于空数组也没问题,但它是未定义的行为,并且在优化时可能会导致一些意外错误打开了。
答案 5 :(得分:0)
不能100%知道我在寻找什么,但我认为真正的答案可能是检查诸如@ed_heel建议的起始项目,但实际上我只需要更改基于范围的for-中检查的内容,循环以使其更加整洁:
for(auto &x : arr)
{
cout << (&x == arr ? "" : ", ") << x;
}
可以工作,因为arr是一个数组(也就是伪装的指针)。