【问题标题】:For Loop That Starts At Middle Of Range And Loops Around从范围中间开始并循环的 For 循环
【发布时间】:2021-12-18 01:23:55
【问题描述】:

是否有可能有一个从范围中间开始的 for 循环,然后循环到范围的开头并继续直到它遍历整个范围?例如,假设我们的范围是 0 到 63,我希望循环从 22 开始,继续循环直到达到 63,然后从 0 开始并循环直到达到 21。这可以用 for 循环吗?或者我需要一个while循环吗?

【问题讨论】:

  • 这在for 循环或while 循环中都是可行的。这两种循环类型可以互换。
  • 是的,使用 i = (i+1) % length 之类的东西来迭代。
  • 你尝试了什么?为什么它不起作用?有几种可能的解决方案,例如,您可以简单地使用两个循环,或者添加偏移量并使用 '%' 运算符,正如 500-InternalServerError 所建议的那样,我相信还有更多方法。
  • 无论您的目标是什么,您都在循环 64 次迭代。所以当然for 循环会起作用。
  • 您可以在int lo = 0; int hi = 63; int start = 22; for (int i = 0; i < (hi - lo + 1); i++) { int index = (start - lo + i) % (hi - lo + 1) + lo; …use index… } 上使用一些变体,这将适用于您的序列,也适用于lo = 27hi = 41start = 36 的序列(产生36、37、38、 39, 40, 41, 27, 28, 29, 30, 31, 32, 33, 34, 35 如果您只是在循环中打印 index 的值)。没有循环变量i 有很多方法可以做到这一点,但是要正确地获得包装和终止条件要困难得多。

标签: c++ c loops for-loop range


【解决方案1】:

我将使用两个循环变量:一个用于计算重复次数,另一个用于处理所需的索引。像这样:

for (int i = 0, j = 22; i < 64; ++i, j = (j + 1) % 64)
    // do something with j

当然,在实际代码中,您可以将幻数 (22, 64) 替换为更清楚地反映所涉及的实际对象的数字。

【讨论】:

  • 这很好用,而范围的下限是0 - 如问题所示。如果下限不为零,则您必须做更多的工作来重新计算j
  • 取模运算符有什么用? Harry 想要从某个中间索引开始的正常 for 循环,不是吗? for (int i = mid_index+1; i
  • @TomeeNS:你的循环什么时候结束?并且您的循环变量与所需值“相差一个”——见证您的呼叫 release_baloon_nr(the_array[i-1]) 而不是在下标中仅使用 i
  • @JonathanLeffler -- re: "如果下限不为零" -- 你是绝对正确的:如果问题不同,答案可能不一样。
  • @TomeeNS -- I 计算重复次数;循环将执行 64 次。 j 是索引;它从 22 开始,一直增加到 63,然后回绕到 0。
【解决方案2】:

是的,您可以为此使用基于范围的for 循环。一个 C++20 STL 示例(带有using namespace std::ranges):

constexpr void foo(auto&& range) {
  auto middle = range.begin() + 22;
  auto parts = {subrange{middle, range.end()}, subrange{range.begin(), middle}};
  for (auto&& elem: parts | views::join) bar(elem);
}

也许有更好看的方式/库。使用适当的 API,它应该类似于

constexpr void foo(auto&& range) {
  for (auto&& elem: range | drop(22) | chain(range | take(22))) bar(elem);
}

编辑:ranges::v3::viewconcat 这是我想象中的chain 的“unpipable”版本)中可以找到几乎相同的“正确 API”:

constexpr void foo(auto&& range) {
    for (auto&& elem: concat(range | drop(22), range | take(22))) bar(elem);
}

【讨论】:

  • 由于您的第二个 sn-p 展示了一个实际上并不存在的库的演示,因此最好描述您正在使用的非标准适配器,特别是, chain。至于做这种事情的库,看看 range-v3,这是 std::ranges 深受启发的东西。
  • @cigien 补充说(甚至找到了现成的 range-v3 实现)。
【解决方案3】:

是的,例如:

for( int i = 22, max = 63, end = i-1 ; i!=-1 ; i=i==end?-1:i==max?0:i+1 )
{
    // do something with i
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    • 1970-01-01
    • 2022-12-16
    • 2012-12-12
    • 2023-04-02
    • 1970-01-01
    相关资源
    最近更新 更多