【问题标题】:C for loop, supposed to be able to omit initialization inside loop itself, doesn't work as intendedC for 循环,应该能够省略循环内部的初始化,但不能按预期工作
【发布时间】:2020-06-23 10:40:12
【问题描述】:

所以我正在慢慢尝试从头开始学习 C。 我在我正在使用的书中提出了一个练习:使用嵌套循环找到毕达哥拉斯三元组。现在我将显示代码。

#include <stdio.h>

int main(void){
int lato1=1;
int lato2=1;
int ipotenusa=1;
  for(;lato1 <= 500; lato1++){
    for(;lato2 <= 500; lato2++){
      for(;ipotenusa <= 500; ipotenusa++){

   
        if (((lato1 * lato1)+(lato2 * lato2))==(ipotenusa*ipotenusa)){
          printf("Tripletta %10d %10d %10d\n",lato1,lato2,ipotenusa);
        }
      }
    }
  }


  return 0;
}

现在,除了糟糕的格式和风格,除了shi*t优化, 如图所示的代码,不起作用。 它只执行最里面的循环,然后程序结束。

但是,如果我在每个循环中初始化每个变量/计数器,那么它就可以工作。 为什么? 我读到 for 循环初始化是有效的,即使没有参数 (;;) 但在这种情况下,我只想在循环之前初始化这些变量,假设因为我想在循环完成后访问这些值,它只是没有看起来不像它应该的那样工作。

英语不是我的主要语言,因此请提前向我道歉。

有人能解释一下是什么问题吗?

编辑1:所以,我不知道是我的英语不好还是其他原因。 我说过,如果我在循环之前声明并初始化变量,就像在我向您展示的代码中一样,它只会通过最内层循环(ipotenusa),并且它会使用以下输出值:1 1 1 then 1 1 2 然后 1 1 3 依此类推,唯一增加的数字是最后一个(ipotenusa);在我们达到 1 1 500 之后,程序突然结束。 然后我说,如果我正常初始化变量,即在 for 循环指令中,那么它会按预期工作。

即使之前声明了它也没有理由不工作。它应该增加的变量值。到目前为止,唯一有用的答案是在循环外初始化一个变量,但在循环语句中为其赋值,但这不是我需要的答案,因为我应该能够跳过循环内的初始化完全声明。

编辑 2:我错了,你们是对的,语言障碍(很可能是愚蠢)当然是造成误解的原因,哈哈。抱歉,感谢您的帮助!

【问题讨论】:

  • 问问自己lato2ipotenusa 的值是多少,这些循环开始的时间。他们都是501吗?如果是这样,为什么这些循环会第二次运行?
  • 换句话说,为什么这些变量会被重置为,呃,0142,除非你 设置它们?第一次可以省略它们的唯一原因是因为它们之前已设置 - 不涉及任何魔法。
  • 有一种形式的for循环有初始化,还有一种形式没有。它们都是有效的。但他们不做同样的事情。你为什么希望他们这样做?
  • 一旦最内层的ipotenusa 循环执行到最后一次(例如ipotenusa &lt;= 500 现在回答为假),发布的代码中的内容将永远 i> 允许该条件再次返回 true 吗?第一个嵌套循环和lato2 &lt;= 500 存在同样的问题。在这两种情况下,一旦它们的条件为假,它们将永远不会返回真,因此循环将永远不会再次进入正文。

标签: c for-loop syntax


【解决方案1】:

你不小心回答了自己的问题:

...在这种情况下,我只想在循环之前初始化这些变量,假设是因为我想在循环完成后访问这些值...

考虑ipotenusa...的值,或者让您的程序在每个循环开始时打印出每个变量的值以进行调试。它看起来类似于以下日志。

lato1: 1
lato2: 1
ipotenusa: 1
ipotenusa: 2
ipotenusa: 3
ipotenusa: 4
ipotenusa: 5
lato2: 2
lato2: 3
lato2: 4
lato2: 5
lato1: 2
lato1: 3
lato1: 4
lato1: 5

内部循环永远不会“重置”,因为您正在保存值。你在这两个方面都没有错,但是你设置了两个相互冲突的需求,而 C 运行时只能给你一个。

基本上,lato2ipotenusa 需要在它们的 for 语句中被初始化(但不一定声明),以便它们被设置再次运行。

int lato1=1;
int lato2;
int ipotenusa;
for(;lato1 <= 5; lato1++){
  for(lato2 = 1;lato2 <= 5; lato2++){
    for(ipotenusa = 1;ipotenusa <= 5; ipotenusa++){
      if (((lato1 * lato1)+(lato2 * lato2))==(ipotenusa*ipotenusa)){
        printf("Tripletta %10d %10d %10d\n",lato1,lato2,ipotenusa);
      }
    }
  }
}

值得指出的是,即使规范可能(或可能不;我不记得而且现在太模糊无法查找)循环变量只存在在循环期间,我从未见过真正做到这一点的实现,因此您会看到很多代码定义了for 内部的变量并在之后使用它。这可能不是很好,像lint 这样的静态检查器可能会抱怨,但它很常见,它可以通过大多数代码审查员,让您了解它是否可以完成。

【讨论】:

    【解决方案2】:

    您的代码完全按照您的要求执行。

    如果你用值 1 初始化 lato2,是什么让你认为初始化会在内部 for 循环的开始处重复?当然不是。您告诉编译器您不希望它再次被初始化。在第一次执行该循环后,lato2 的值为 501,它将永远保持该值。

    即使它没有产生错误,将初始化和 for 循环相距甚远也是非常非常糟糕的风格(在专业环境中无法通过代码审查,因此必须进行更改)。

    for (int lato2 = 1; lato2

    【讨论】:

    • 看到我说:“现在,除了糟糕的格式和样式,除了shi*t优化之外,如图所示的代码不起作用。它只执行最里面的循环,然后程序结束。”我真正的意思是:我不在乎它是否漂亮、时尚、晦涩或其他什么,我想知道它为什么不起作用。谢谢。
    • @ettoralk 这个答案(以及 John C 的答案)说明了它为什么不起作用。您认为这些您需要的答案缺少什么?
    • @dbush 它缺乏正确性,这就是它所缺少的。我的变量在循环之外初始化,但是循环增加 sn-p (变量 ++)应该每次将值增加 1。它不会对所有变量执行此操作,而仅对最内层循环中的变量执行此操作。我的问题是为什么?当所有变量都以相同的方式初始化时,为什么它只适用于最内部?该值可用,所有循环都可以访问它们的值,但除了最后一个循环之外它不起作用。
    • @ettoralk 是正确的。您在任何循环之外将 ipotenusa 初始化为 1。当你第一次完成内循环时,ipotenusa 的值为 501。当中间循环开始第二次迭代时,它再次启动内循环但 ipotenusa 仍然是 501,因为你没有更改它,所以内循环不再运行。
    • @ettoralk 打印 1 1 500 后程序不会突然结束。它只是永远不会再次进入内部循环,因为ipotenusa 在您每次尝试内部循环时都是 501。
    【解决方案3】:

    一种方法是 - 在循环外部声明变量并在内部初始化它们。这样,您可以在循环之后访问变量。

    #include <stdio.h>
    
    int main(void){
    int lato1, lato2, ipotenusa;
    for(lato1=1; lato1 <= 500; lato1++){
      for(lato2=1; lato2 <= 500; lato2++){
        for(ipotenusa=1; ipotenusa <= 500; ipotenusa++){
    
       
          if (((lato1 * lato1)+(lato2 * lato2))==(ipotenusa*ipotenusa)){         
            printf("Tripletta %10d %10d %10d\n",lato1,lato2,ipotenusa);
          }
        }
      }
    }
    
    
      return 0;
    }
    

    【讨论】:

    • OP 已经说过这种方法确实有效,但想知道为什么省略初始化器不起作用。
    【解决方案4】:

    您正在使用在 for 循环之外初始化的变量。通常情况下,当我们使用内部循环(嵌套循环)时,我们打算每次都用基值初始化它,但在你的情况下,它永远不会这样做。由于您已经在 for 循环之外初始化了变量,因此它会在其生命周期内保持其值,当然这在这种情况下是 main 函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-09
      • 1970-01-01
      • 2016-11-02
      • 1970-01-01
      • 2017-03-12
      • 1970-01-01
      相关资源
      最近更新 更多