【问题标题】:What is this syntax in while loop condition?while 循环条件中的这种语法是什么?
【发布时间】:2014-03-08 14:11:52
【问题描述】:
while ( (i=t-i%10 ? i/10 : !printf("%d\n",j)) || (i=++j<0?-j:j)<101 );

我在 codegolf 上遇到过这个

请解释?:的用法,为什么while循环后面没有语句?至于为什么括号后有;

【问题讨论】:

  • 在您喜欢的搜索引擎中查找“条件运算符”。

标签: c++ c syntax


【解决方案1】:

在while循环的括号内有一个布尔运算:

while (boolean);

由于三元运算符是布尔运算符,因此完全合法。

那么这是做什么的呢?看起来像模运算,打印范围高达 101。

我同意它神秘而晦涩。它看起来更像是代码混淆亚军。但它似乎是可编译和可运行的。你试过了吗?它做了什么?

【讨论】:

    【解决方案2】:

    ?: 是一个三元运算符。

    &lt;A&gt; ? &lt;B&gt; : &lt;C&gt; 形式的表达式计算结果为:

    • 如果&lt;A&gt; 为真,则计算结果为&lt;B&gt;
    • 如果&lt;A&gt; 为假,则计算结果为&lt;C&gt;

    while 循环后面的; 表示一条空指令。相当于写

    while (&lt;condition&gt;) {}

    您发布的代码似乎被混淆了。

    【讨论】:

    • “混淆”:在您最喜欢的搜索引擎中查找“codegolf”;-)
    【解决方案3】:

    请解释?:的用法

    这就是条件运算符a ? b : c 评估 a 并将其转换为布尔值。然后它评估b是否为真,或c如果为假,表达式的整体值是评估bc的结果。

    所以第一个子表达式:

    • t-i%10 分配给i。该表达式的结果是 i 的新值。
    • 如果i不为零,则表达式的结果为i/10
    • 否则,打印j,表达式的结果为零(因为printf 返回打印的非零字符数,! 转换为零)。

    然后,|| 之后的第二个子表达式仅在第一个表达式的结果为零时才被计算。我会让你弄清楚那是做什么的。

    为什么while循环后面没有语句?

    有一个空语句;,所以循环体什么也不做。所有动作都发生在条件表达式的副作用中。当代码的目的是让读者感到困惑时,这是一种常见的技术;但请不要在编写您关心的任何人可能需要维护的代码时做这种事情。

    【讨论】:

      【解决方案4】:

      这是Conditional Operator(也称为三元运算符)。

      if (?)条件doA else (:)doB做相同的操作是一行语法;

      在你的例子中:

      (i=t-i%10 ? i/10 : !printf("%d\n",j)
      

      相当于

      if (i=t-i%10)
        i/10;
      else
        !printf("%d\n",j);
      

      【讨论】:

        【解决方案5】:

        ?: if then else 的简写形式

        (i=t-i%10 ? i/10 : !printf("%d\n",j)<br>
        

        等于

        if( i= t-i%10 )
        then { i/10 }
        else { !printf("%d\n",j) }
        

        当 || 之前的语句时,您的 while 循环将运行。为真或 || 之后的语句是真的。

        请注意,您的代码没有任何意义。

        【讨论】:

          【解决方案6】:

          while ( (i=t-i%10 ? i/10 : !printf("%d\n",j)) || (i=++j

          在我可以为你做的最可读的情况下,它相当于:

          while (i < 101)
          {
            i = (t - i) % 10;
            if (i > 0)
            {
              i = i / 10;
            }
            else
            {
              printf("%d\n",j);
            }
          
            i = ++j;
            if (i < 0)
            {
              i = i - j;
            }
            else
            {
              i = j;
            }
          }
          

          您好。

          【讨论】:

            【解决方案7】:

            我是该代码的骄傲实施者。这是完整版:

            main()
            {
                int t=getchar()-48,i=100,j=-i;
                while ((i=t-i%10?i/10:!printf("%d\n",j)) || (i=++j<0?-j:j)<101  );
            }
            

            这是我对编程挑战或“代码高尔夫”的提交,其中要求您创建最小的程序,该程序将接受一个数字作为参数并打印 -100 到 100 范围内的所有数字,包括给定的数字.禁止使用字符串或正则表达式。

            Here 是挑战的链接。

            关键是它把所有的工作都放在一个计算为布尔值的语句中。实际上,这是将两个不同的 while 循环合并为一个的结果。相当于下面的代码:

            main()
            {
              int i,t=getchar()-'0',j=-100;
              do 
              {
                  i = j<0? -j : j;
                  do
                  {
                      if (t == i%10) 
                      {
                         printf("%d\n",j);
                         break;
                      }
                  }
                  while(i/=10);
              }
              while (j++<100);       
            }
            

            现在让我们稍微剖析一下这个循环。

            首先,初始化。

            int t=getchar()-48,i=100,j=-i;
            

            将从标准输入中读取一个字符。您应该输入一个介于 0 和 9 之间的数字。48 是零字符 ('0') 的值,因此 t 最终会保存一个介于 0 和 9 之间的整数。

            i 和 j 将是 100 和 -100。 j 将在 -100 到 100(含)范围内运行,并且 i 将始终保持 j 的绝对值。

            现在循环:

            while ((i=t-i%10?i/10:!printf("%d\n",j)) || (i=++j<0?-j:j)<101  );
            

            我们把它读成

            while ( A || B ) /* do nothing */ ;
            

            其中 A 等于 (i=t-i%10?i/10:!printf("%d\n",j)) 且 B 等于 (i=++j

            关键是 A 被评估为布尔值。如果为真,则根本不会评估 B 并且循环将再次执行。如果为假,B 将被评估,反过来,如果 B 为真,我们将再次重复,一旦 B 为假,循环将被退出。

            所以 A 是内循环,B 是外循环。让我们解剖它们

            (i=t-i%10?i/10:!printf("%d\n",j))
            

            它是 i = CONDITION? 形式的三元运算符? X:Y;这意味着将评估第一个条件。如果为真,i 将被设置为 X 的值;否则我将被设置为 Y。

            这里的 CONDITION (t-i%10) 可以读作 t - (i%10)。如果 i 模 10 与 t 不同,这将评估为 true,如果 i%10 和 t 是相同的值,则评估为 false。

            如果不同,则等价于 i = i / 10; 如果相同,则操作为 i = !printf("%d\n",j)

            如果你仔细想想,你会发现它只是一个循环,检查 i 中整数中的任何十进制数字是否等于 t。

            循环将继续进行,直到耗尽 i 的所有数字(i/10 将为零)或运行 printf 语句。 Printf 返回打印的位数,应始终大于零,因此 !printf(...) 应始终评估为 false,同时终止循环。

            现在对于 B 部分(外循环),它只会增加 j 直到达到 101,并将 i 设置为 j 的绝对值。


            希望我说得有道理。

            是的,我通过在 google 中搜索我的代码找到了这个帖子,因为我找不到挑战帖子。

            【讨论】:

              猜你喜欢
              • 2021-08-17
              • 2018-01-21
              • 2011-10-23
              • 2011-07-22
              • 2012-07-29
              • 2020-08-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多