【问题标题】:Using a for-loop in C to test the return value of a function在 C 中使用 for 循环来测试函数的返回值
【发布时间】:2020-02-05 22:00:33
【问题描述】:

我对编码非常陌生,尤其是 C,所以我决定参加 CS50 课程作为语言的介绍。我刚看完关于 C 的第一堂课,为了测试我对该主题的了解,我尝试编写一个简短的小程序。我也在使用课程的库来实现get_int() 函数。

目标是测试用户的输入并检查它是否小于或等于 10。如果它与参数匹配,程序应该打印“成功!”消息和退出;否则,它应该再次要求输入。如果输入值超过 10,程序会按预期响应,但如果您输入 10 或更少的值,它最终会在实际退出之前再要求您输入一次。我认为这可能与“for”循环有关,但我就是想不通。

我的代码:

#include <stdio.h>
#include <cs50.h>
#include <stdlib.h>

int check_for_value();

int main()
{
    for(check_for_value(); check_for_value() != 1;  check_for_value())
    {
        printf("Failed!\n");
    }
    exit(0);
}

int check_for_value()
{
    int i = get_int("Your value: \n");

    if(i <= 10)
    {
        printf("Success!\n");
        return 1;
    }    
    else
    {
        printf("Try again!\n");
        return 0;
    }
}

【问题讨论】:

    标签: c loops for-loop cs50


    【解决方案1】:

    这并没有完全按照您的想法进行。在您的 for 循环中,每次您编写 check_for_value() 时,都会调用该函数。所以它会第一次调用它,返回值无关紧要。它将再次为中间语句调用它,然后该值将很重要,因为您将输出与不等于 1 进行比较。然后它将再次在第三条语句中调用该函数,这再次无关紧要。通常对于这样的事情,你会使用一个while循环来代替。下面是一个例子:

    int ret = check_for_value();
    while(ret != 1) {
        printf("Failed\n");
        ret = check_for_value();
    }
    
    printf("Success\n");
    

    从技术上讲,for 循环也可以按以下方式工作:

    for(int ret = check_for_value(); ret != 1; ret = check_for_value()) {
        printf("Failed\n");
    }
    

    【讨论】:

    • 那个替换可以简化为while (check_for_value() != 1) printf("Failed\n");,不是吗?
    • 嗯,是的,但我认为这对初学者来说更容易理解。更短的代码并不总是意味着它更容易阅读。此外,如果编译器很聪明,那么它也会有效地做同样的事情。
    • 嗯——我想我认为较短的代码更容易理解,但我已经用 C 编码足够长的时间(超过 35 年),以至于我做出任何猜测“对初学者来说更容易”必须用一小撮盐来处理。
    【解决方案2】:

    for循环看起来很简单

    for ( ; !check_for_value(); )
    {
        printf("Failed!\n");
    }
    

    在这种情况下最好使用while循环

    while ( !check_for_value() )
    {
        printf("Failed!\n");
    }
    

    至于你的 for 循环

    for(check_for_value(); check_for_value() != 1;  check_for_value())
        ^^^^^^^^^^^^^^^^^                           ^^^^^^^^^^^^^^^^^
    

    那么带下划线的函数调用不会被测试。

    还要记住,这样的 for 循环定义

    for(int ret = check_for_value(); ret != 1; ret = check_for_value()) {
        printf("Failed\n");
    } 
    

    是一种非常糟糕的编程风格。函数调用存在冗余记录。循环体中不使用中间变量ret。所以它的声明也是多余的。永远不要使用这种编程风格。

    注意,根据C标准,没有参数的函数main应该声明为

    int main( void )
    

    和声明

    exit( 0 );
    

    是多余的。

    【讨论】:

    • 请注意 C11 标准 §6.5.3.4 ¶8。它在一个示例中说明了int main() — 技术上不规范,但强烈表明只要您不打算调用main() 就可以使用int main()(因为它不提供原型对于main())。最好使用int main(void)——但“根据 C 标准”夸大了你的情况。
    • @JonathanLeffler 我确信这是一个标准缺陷,因为它与标准本身相矛盾。
    • C11 §5.1.2.2.1 表示:“或等价物”,int main() 中的空括号基本等价于int main(void),只是后者给了main() 的原型,而前者没有.另请参阅:§6.7.6.3 ¶20 — 如果是错误,则会发生两次(两次都出现在非规范示例中)。
    • @JonathanLeffler 有一个脚注“10)因此,int可以替换为定义为int的typedef名称,或者argv的类型可以写成char ** argv,以此类推”
    • 是的,'等等'允许int main()。至少,这是一个合理的解释。
    猜你喜欢
    • 2020-10-09
    • 1970-01-01
    • 2015-08-08
    • 2020-01-10
    • 2019-02-08
    • 1970-01-01
    • 2017-10-13
    • 2015-08-08
    • 1970-01-01
    相关资源
    最近更新 更多