为什么当条件为假时我不能退出for循环?

Why can't I exit the for cycle when the condition becomes false?

我希望循环在用户键入“0 00 00”时结束。这是代码:

main()
{
    int i, o[128], m[256], s[256];
    for(i = 0; o[i] != 0 && m[i] != 00 && s[i] != 00; i++)
        scanf("%d %d %d", &o[i], &m[i], &s[i]);
    printf("ok\n");
}

但结束它的唯一方法是输入一些字符。

您必须了解 for 循环中的操作顺序才能找出答案:

  1. 执行初始化操作,即i=0
  2. 在进入循环之前检查条件。这是您的第一个问题,因为 o[]m[]s[] 未初始化。
  3. 循环体被执行
  4. i++执行
  5. 控制传递到步骤 2

注意第2步的条件总是"ahead"循环体,检查还没有初始化的元素

在这种情况下,最好使用 break 语句从内部结束循环,如下所示:

for (int i = 0 ; i != 128 ; i++) { // Preserve the boundaries of o[128]
    scanf("%d %d %d", &o[i], &m[i], &s[i]);
    if (o[i] == 0 && m[i] == 0 && s[i] == 0) {
        break;
    }
}

您的代码有几个问题:

  • for 循环在 执行其主体之前检查其条件。在第一轮中,您将检查未初始化的变量。请改用 do ... while() 循环或初始化数组。
  • 您无法将输入解析为整数并检查双零。如果你想这样做,你必须将这部分输入解析为字符串。
  • 您应该检查 scanf 的 return 值以检测错误。

如果您被迫使用 for 循环并依赖其条件来打破它,您可以这样解决这个问题:

int main(void)
{
  int o[128 + 1] = {-1}, m[256 + 1] = {-1}, s[256 + 1] = {-1};

  for(size_t i = 1; /* Use size_t to index arrays */
    i < (128 + 1) && o[i-1] != 0 && m[i-1] != 0 && s[i-1] != 0; 
    i++) {
    scanf("%d %d %d", &o[i], &m[i], &s[i]);
  }

  puts("ok");
}

请注意,数组位置 0 处的值未被读取,而是固定为 -1

如果您的代码依赖于基于 0 的索引,您可以通过以下方式进行欺骗:

int main(void)
{
  int oa[128 + 1] = {-1}, ma[256 + 1] = {-1}, sa[256 + 1] = {-1};
  int *o = oa + 1, *m = ma + 1, *s = sa + 1;

  for(size_t i = 0; /* Use size_t to index arrays */
    i < 128 && o[i-1] != 0 && m[i-1] != 0 && s[i-1] != 0; 
    i++) {
    scanf("%d %d %d", &o[i], &m[i], &s[i]);
  }

  puts("ok");
}

然而,更好的解决方案是:

int main(void)
{
  int o[128], m[256], s[256];

  {
    ssize_t i = -1; /* If ssize_t isn't available use any signed integer wide enough. */
    do {
      ++i;
      scanf("%d %d %d", &o[i], &m[i], &s[i]);
    } while (i < 128 && o[i] != 0 && m[i] != 0 && s[i]);
  }

  puts("ok");
}

如当前所写,i检查条件之前递增 ,因此每次您只是检查 不确定的值,表现出未定义的行为。

使用 do-while 确保循环至少执行一次,同时让您有更多控制权:

i = -1; // Note the -1 here!
do{
    i++;
    scanf("%d %d %d", &o[i], &m[i], &s[i]);
} while (o[i] != 0 && m[i] != 0 && s[i] != 0);