【问题标题】:Why can't I declare more than one variable in a for loop's initial statement?为什么我不能在 for 循环的初始语句中声明多个变量?
【发布时间】:2019-12-29 11:25:51
【问题描述】:

当使用带有一个变量的 a 时,我们将它声明为 0,因为 i=0 就像这里一样

但是当我们使用两个变量时,就像我添加 n = strlen 以使代码更高效时,不声明 i=0 而是使用逗号并声明 n=strlen(s)。为什么我们不能使用 'i=0;'就像在前面的代码中所做的那样?

编辑:cs50.h 是沙盒 cs50 的一部分,由哈佛制造。

#include <stdio.h>
#include <string.h>

int main(void)
{
    string s = get_string("Input:  ");
    printf("Output: ");
    for (int i = 0; i < strlen(s); i++)
    {
        printf("%c\n", s[i]);
    }
}
#include <cs50.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
    string s = get_string("Input: ");
    printf("Output:\n");
    for (int i = 0, n = strlen(s); i < n; i++)
    {
        printf("%c\n", s[i]);
    }
}

【问题讨论】:

  • 您可以声明多个变量。这里的两个代码示例都很好。
  • 不,用逗号它仍然是一个声明。 int i = 0, n = strlen(s);int i = 0; 都声明了一个变量 i 并将其初始化为 0
  • @animesh 确实没有任何理由认为您的首选版本“更高效”。对你来说,它看起来像是更有效地利用空间,但很难猜测,尤其是在没有很多经验的情况下,编译器会把它变成什么。最好避免养成这种想法的习惯,因为代码首先应该是人类可读的。
  • @KamilCuk 所以我可以用逗号分隔多个变量,但最后一个变量必须用分号?
  • 因为;分隔了for循环的3个子句,所以不能在声明之间使用。

标签: c cs50


【解决方案1】:

来自 C 标准 ISO/IEC 9899:TC3 / ISO/IEC 9899/C11for 语句的语法描述,§(6.8 .5) 迭代语句,有两种不同的形式:

for ( expression_opt ; expression_opt ; expression_opt ) statement

for (declaration expression_opt ; expression_opt ) statement

请注意,在第一种形式中,我们在第一个位置有一个表达式,尽管它是可选的,因为所有 3 个字段都是可选的,并且语句形式的所有 3 部分都由用作分隔符的 ; 分号分隔。

在第二种形式中,我们可以看到括号中的第一个元素是声明而不是表达式,我们还可以注意到没有分号分隔它。这是因为声明本身总是以分号结束

(6.7) 声明段描述声明的语法:

declaration-specifiers init-declarator-list_opt ;

如您所见,declaration 始终以分号结尾。

一个声明当然可以采用多个声明的形式,如下所示:

for (int i = 0, n = strlen(s); i < n; i++)
{
    printf("%c\n", s[i]);
}

所以您使用的是分号分隔声明的第二种形式(不是for 的第一部分)

使用多个分号只是语法错误。

【讨论】:

    【解决方案2】:

    不确定我是否理解这个问题(尽管我喜欢它)。您的代码 sn-ps 都可以工作,不是吗?请注意,我们不知道 cs50.h 中的内容,但我尝试编译它,它工作(编译和运行)。

    #include <stdio.h>
    #include <string.h>
    
    int main(void) {
      char *s = "Hello world!";
      printf("Output:\n");
      for (int i = 0, n = strlen(s); i < n; i++) {
        printf("%c\n", s[i]);
      }
    }
    

    这里有两件事可能是相关的; - for 的工作原理和 - 变量声明/初始化的工作原理。

    你可以这样想forfor(AAA; BBB; CCC) DDD; 是一样的

    { // Important!
      AAA;
      while(BBB) {
        {
          DDD;
        }
        CCC;
      }
    } // Important!
    

    // Important! 大括号很重要,因为 for 引入了一个新范围,即 infor 循环之外/之后无法访问。

    另一件事是声明/初始化。所以

    int i = 0, n = strlen(s);
    

    是两个变量的初始化:in。我不是 100% 确定正确的词汇和规则(您可以查阅标准),但想法是声明看起来像: TYPE VAR1, VAR2, ..., VARn 其中VARx 是声明的变量名,或者是“赋值”,在这种情况下是初始化。

    更新/第 2 部分: 通常我会怎么做是这样的:

    const int len = strlen(s);
    // Good practice to declare const what every you know wont change
    for(int i = 0; i < len; i++) {
      // whatever
    }
    

    但是,如果可以使令人困惑的逗号/分号保持一致,并且由于分号是必须,让我们尝试将所有内容都设为分号,我已经尝试过:

    for ({int i = 0; int n = strlen(s); }; i < n; i++) {
      // what ever
    }
    

    这没有编译,但它也没有意义,因为如果这会“工作”(在某种意义上我认为我可以但实际上不能),in 将被声明在小块中,它在其他任何地方都无法访问,即在i &lt; n 中将无法访问。所以为了让它们可以访问,我们可以试试这个:

    int i, n;
    for ({i = 0; n = strlen(s); }; i < n; i++) {
      printf("%c\n", s[i]);
    }
    

    如果上面提到的for-while 等价是 100% 正确的,现在这应该可以工作,但显然AAA 必须是一个单一的声明(通常是一个声明)并且它可以不要成为一个块,即{...}。确切的编译器错误:

    cc     hola.c   -o hola
    hola.c: In function ‘main’:
    hola.c:8:8: error: expected expression before ‘{’ token
        8 |   for ({
          |        ^
    make: *** [<builtin>: hola] Error 1
    

    但是正如您所看到的,它已经非常丑陋了……所以是的,您需要使用, 来分隔声明/初始化,并使用; 来终止它。

    【讨论】:

    • 所以声明多个变量时使用逗号,最后一个以分号结尾。 cs50.h 是 harvard 制作的沙盒 cs50 的头文件。它不会真正影响 for 循环中的任何内容。无论如何,我得到了我的答案。谢谢
    • 阿德里安·摩尔在哪里?在forwhile 中?我认为这样的作品!我尝试了其他方法(我将在几秒钟内更新答案),因为如果它是单个语句,您可能不需要它。
    • Animesh Singh 基本上是的。所以你程序中最小的“单元”是一个语句,它必须通过在末尾放置一个分号来分隔。但是一个声明语句可以声明多个变量,它们之间用逗号分隔(最后一个语句分隔分号)。
    • @Emil 我建议在您的while 示例中添加{ DDD; }。因为用户可以在循环体中声明一个int d,但是在for 循环的CCC 子句中不能访问它。
    • 专注于整个答案......但我猜你是对的。将相应更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    相关资源
    最近更新 更多