0

[编辑]哎呀,代码中有一个错误,现在对这个问题的所有回答似乎都很奇怪,但基本上 for 循环曾经是 for(i=0; i<15; i++)。我还进行了编辑以使问题更清楚。[/EDIT]

我正在尝试创建一个 for 循环,它检查一个 16 元素数组,因此它从 0 循环到 15。然后我稍后使用 i 变量,但有时 i == 16,这会导致超出范围的问题。

我有一个解决方案,但它看起来并不优雅,这让我觉得我错过了一些东西。我试过 while 循环,但我永远无法让任何循环从 0 变为 15,并且永远不会以大于 15 的值结束。

有没有办法让一个循环去检查数组的所有 16 个元素,同时在循环结束时永远不会大于 15?

int i;

for(i=0; i<16; i++)
{
    someClass.someMethod(i);

    if(someClass.Test())
    {
        break;
    }
}



if (i == 16)
{
    i = 15;
}
4

15 回答 15

6

i我建议在循环完成后使用其他变量。使用 for 循环而不是 while 循环的标准是您事先知道 for 循环将执行多少次。如果您已经知道这一点,只需将一些其他变量设置为循环的结束值并使用它而不是提供i双重目的。

int j = 15;

for(int i=0; i <= j; i++)
{
    someClass.array[i];
}

// continue on using j, which value hasn't changed
于 2009-04-28T22:51:52.743 回答
3

对于初学者来说,您的示例代码从 0 循环到 14。但是如果您从 0 循环到 15,自然 i 必须是 16才能结束循环。发生的事情是它变成了 16,然后你的循环注意到它超出了界限并爆发了。如果您希望它在 15 处结束,老实说,最简单的方法就是在循环结束后递减。

于 2009-04-28T22:49:18.427 回答
3

i 在最后一次检查时递增为 16,不小于 15,因此循环退出时 i 为 16。

于 2009-04-28T22:50:26.130 回答
3

也许知道这一点很有用:

for (before; check; after) { body } 

它与以下内容相同:

before 
while(check) { 
  body 
  after 
} 

如果你在那个术语中思考你的 for 循环,也许你会很容易地找出为什么 i 在出口处是 16。

于 2009-04-28T22:58:55.300 回答
3

您的方法似乎存在一些基本缺陷。

  1. 您不应该真正在循环范围之外使用索引变量。
  2. 您应该使用变量或函数来确定循环的限制。
  3. 最好使用迭代器而不是数字索引。
  4. 通用算法可以消除循环的需要。

只是我的 0.02 美元。

于 2009-04-29T03:22:04.247 回答
1

所以 - 如果你正在检查一个 16 元素数组,通常你会这样做:

for(i=0; i<16; i++)

如何工作,是从三个中的第一个语句开始:

i=0

然后它会在第二个语句中进行检查:

i < 16 // True here, since 0 < 16

这发生在你的循环之前。然后它使用该集合运行循环块:

someClass.array[i]; //0

最后,它做了最后的声明:

i++

然后它按顺序重复第二个和第三个语句。

在最后一次运行之前,i == 14,然后它执行 i++,将 i 设置为 15,并执行该块。最后,它执行 i++,设置:

i==16

此时,条件不再成立:

i < 16 // False, since i==16

此时,您的块没有执行,但 i 仍设置为 16。

于 2009-04-28T22:53:11.007 回答
0

你一定错过了什么。

在这个循环中,它甚至不会达到 15,你需要说 i <= 15,只要 i = 14 它就会运行一次并保释。

于 2009-04-28T22:50:03.043 回答
0

for循环等效于以下while循环:

i = 0;
while(i < 16) {
    someClass.array[i];

    i++;
} // while

i需要达到 16 才能正确退出循环。

于 2009-04-28T22:57:39.560 回答
0

从技术上讲,有一些方法可以编写循环,例如i退出循环时为 15,但您不应该这样做:

int i = 0;
while (1) {
    someclass.someMethod(i);
    if (i < 15) {
        i++;
    } else {
        break;
    }
}

是的,它可以满足您的要求。但是流量很可怕。

于 2009-04-28T23:10:54.960 回答
0

您无法使用内置循环结构来完成此操作,正如 Bill The Lizard 所说,您可能真的不想重用 for 循环变量。

但是,如果你真的想要,这里有一种方法。诀窍是将循环条件放在循环的中间:

int i = 0;
while (true)
{
    someclass.array[i];
    if (i == 15)
        break;
    ++i;
}
于 2009-04-28T23:16:32.263 回答
0

这里要理解的关键问题是“i 的什么值导致测试成功?”这个问题有 17 个不同的答案。i 可以在 {0, 1, ..., 15} 中,或者没有 i 的值会导致测试成功,在这种情况下用 i == 16 表示。因此,如果 i 仅限于 16 个值,则无法回答该问题。

在某些合法情况下,您不想超过最后一个有效值。例如,如果您有 256 个值并且由于某种原因您只有一个字节可以计算。或者,就像我最近发生的那样,您只想检查数组的每个第 i 个元素,并且迭代器的最后一个添加使您远远超出数组的末尾。在这些情况下,循环展开是必要的。

但是,对于这个问题,使用标志会更干净:

bool flag = false;
for (int i = 0; i < 15; ++i) 
{
    someClass.someMethod(i);

    if (someClass.Test())
    {
        flag = true;
        break;
    }
}

然后很清楚测试是否成功。

于 2009-04-29T00:52:14.810 回答
0

如果您的循环自然终止,而不是中断,i 是 16。没有办法避免这种情况。如果您想要 i 最终为 15 或更少,您的代码是完全可以接受的:

int i;
for (i=0; i<16; i++) {
    someClass.someMethod(i);
    if (someClass.Test())
        break;
}
if (i == 16)
    i = 15;

i在循环体之后从 16更改为 15 的任何内容都可以:

if (i == 16) i = 15;
i = (i == 16) ? 15 : i;
i = MAX (15,i); /* where MAX is defined :-) */

等等。

但是,这假设它将i用于有意义的事情,作为关于该循环的后置条件。我发现这种情况很少见,人们倾向于在重新使用之前重新初始化它(例如另一个 for 循环)。

此外,您正在做的事情使得很难(甚至不可能)确定作为后置条件,您的循环是正常终止还是由于someClass.Test()返回 true 而提前终止i == 15。这意味着使用 i 做出进一步的决定充满了危险。

我的问题是:你为什么认为你需要在i15 岁或以下离开?

于 2009-04-29T01:49:02.740 回答
0

我正在尝试创建一个 for 循环,它检查一个 16 元素数组,因此它从 0 循环到 15。然后我稍后使用 i 变量,但有时 i == 16,这会导致超出范围的问题。

您需要检查您的 for 循环没有中断的情况,因为此信息确定您想要对 i 执行的任何操作是否有效。

有几种方法可以做到这一点。一种是在 bool 中跟踪它,例如“foundClass”或“testSucceeded”。将其默认为 false,然后在休息时将其设置为 true。稍后在“if (foundClass) { }”块中的函数中包含对 i 的任何使用。

另一种是只做你已经做过的事情。尽管您的后备看起来根本不正确。如果您将 i 设置为 15,那么您就是在对您的代码撒谎并告诉它 someClass.Test() 对于 i == 15 成功,这是不正确的。避免将值设置为错误的值,这样您的代码以后就不会出错。稍后在代码中围绕 i 的实际使用进行边界检查要好得多。

于 2009-04-29T02:23:38.460 回答
0
for(int i=0; i<17; i++)
{    
  if(i<16)
  {
     someClass.someMethod(i); 
     if(someClass.Test())   
     {        
       break;    
     }
  }
  else if(i==16)
  {
     i=15;
  }
}
于 2009-05-01T08:18:51.990 回答
0

如果您说您有一个包含 16 个元素的数组,则不必定义它,使用该数组来获取该信息(请勿重复信息)

之后,如果您想再次获取最后一个索引,请使用数组来获取该信息。

for(int i = 0; i < myArray.length; ++i){
       myArray[i].somemethod();
}
// lastindex = myArray.length-1;
于 2010-11-16T09:37:27.107 回答