【问题标题】:C - use of undeclared identifier in a function. CS50C - 在函数中使用未声明的标识符。 CS50
【发布时间】:2018-08-05 22:13:11
【问题描述】:

我正在重写我的 CS50 学分解决方案以使用函数。 在定义 readCardNumber() 时偶然发现错误。

long long readCardNumber()
{
    do
    {
        long long result = get_long_long("Enter card number to verify: \n");
        if (result < 0)
        {
            printf("Retry: \n");
        }
    }
    while (result < 0);

    return result;
}

我正在使用 CS50.h https://reference.cs50.net/cs50/get_long_long 来获取号码。由于以下原因,我无法编译此解决方案:

error: use of undeclared identifier 'result'

有经验的人可以解释一下这里的问题吗?我确实在代码开头声明了函数,并在函数中声明并初始化了结果。 验证该数字的更好方法是什么?

https://docs.cs50.net/2018/x/psets/1/credit/credit.html - 我正在尝试返工的解决方案规范。

【问题讨论】:

  • C 和大多数编程语言中,在{ ... } 中声明一个变量将不允许该变量对代码库的其他部分可见。

标签: c function validation cs50


【解决方案1】:

result 变量在do...while 块内声明。块外不可见,包括while的条件。

您需要将变量定义移出循环:

long long result;
do
{
    result = get_long_long("Enter card number to verify: \n");
    if (result < 0)
    {
        printf("Retry: \n");
    }
}
while (result < 0);

【讨论】:

    【解决方案2】:

    这是范围的问题。在 C 中,作用域由{} 定义。变量在其声明的范围的末尾不再存在。 (好吧,静态变量不会,但它们无法访问。除非你有指向它们的指针。)

    您需要做的是将声明移到循环之外。

    不过我想强调的是,在变量使用的范围内声明变量是一种非常好的做法。它显着降低了错误的风险。如果变量仅在循环内使用,则在循环内声明它。这与除非必要,否则不应使用全局变量的原因基本相同。

    【讨论】:

      【解决方案3】:

      result 超出范围时,您执行return result;。但是您的代码包含冗余:您测试result &lt; 0 两次。我建议更改结构以避免这种情况,并具有修复原始问题的额外副作用:

      long long readCardNumber(void)
      {
          for (;;)
          {
              long long result = get_long_long("Enter card number to verify: \n");
              if (result >= 0)
                   return result;
      
              printf("Retry: \n");
          }
      }
      

      【讨论】:

        【解决方案4】:

        这是关于do/while 语句的那些不方便甚至“不自然”的事情之一:您在循环体内声明的所有内容对于语句的while 部分中的条件都是不可见的。这些标识符的范围在while 部分之前的} 结束。

        这通常会迫使用户在循环之前声明变量

        long long result;
        do
        {
          result = get_long_long("Enter card number to verify: \n");
          if (result < 0)
            printf("Retry: \n");
        }
        while (result < 0);
        

        为这个解决方案付出的代价是

        1. result 的范围超出循环的不必要扩展
        2. 不再可能在声明时有意义地初始化变量

        对于我们中的许多人来说,这太令人不快了,我们宁愿切换到 do/while(1) 方法,中间使用 break 来终止循环

        do
        {
          long long result = get_long_long("Enter card number to verify: \n");
          if (result >= 0)
            break;
        
          printf("Retry: \n");
        }
        while (1);
        

        显然,这也不完美。自己选择,你更喜欢哪种方法。

        在后一种情况下,do/while(1) 用作表达从中间退出的循环的“惯用”方式。为此,其他人可能更喜欢for (;;)while(1),从而完全避免使用do/while 语句。

        【讨论】:

        • 在这种情况下,在整个循环之后需要变量'result',所以这个建议不起作用。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多