【问题标题】:Doing a for loop in a sequential evaluation in c在 c 中的顺序评估中执行 for 循环
【发布时间】:2020-04-09 12:27:00
【问题描述】:

我正在尝试在 C 中使用顺序求值运算符 (,),并且我想在第一个表达式中执行 for 循环,如下所示:

( for(initialization;condition;increment) foo() , bar() )

但是写那行我得到一个error: expected expression

我不会惊讶地发现这是一件不可能的事情,尽管让我犹豫不决的是我可以执行 logical_expression ? expression_true : expression_false 形式的伪 if 语句。

有没有办法做到这一点?还是我需要在外部创建 for 循环?

编辑:

我决定更新我的问题以提供有关我的问题的更多背景信息。

我有两个函数,我们称它们为baz()qux()qux()baz() 的反函数,因此对于任何给定的输入,qux(baz(input)) 应该返回输入。

具体来说,baz() 接受一个字符数组,它们都在'0''9' 之间,并以与该问题无关的不同格式返回该数字的表示。当我们将不同的表示传递给quz() 时,我们会返回原始数组。

所以我想构建自己的代码来测试任意数量的案例,看看qux(baz(input)) 是否返回了所需的结果。我想在尽可能少的代码行中做到这一点(只是将所有行放在同一个行中,用分号分隔,这不是我想要的)。

我知道我可以使用像 CUnit 这样的框架来完成它,但我想自己完成它。而且我知道以这种方式编写我的代码会使其不可读和混淆,但我想将其作为个人挑战。所以我写了(不要试图理解它,它几乎是不可读的代码):

#include "my_lib.h"
#include <stdlib.h>
#include <stdio.h>
int main() {
    int i, errors_size = 0, str_size = 1;
    char *str, **errors = NULL;
    (str = malloc(sizeof(*str)*2) , str[0] = '1' , str[1] = '\0');
    for( (i = 0) ; i < 10000 ; ( i++ , (str[str_size-1] == '9') ? ( ( str[str_size-2] == '9' ? str[str_size-1] = '0' , str_size++, str = realloc(str, sizeof(*str) * (str_size+1)), str[str_size- 1] = '0', str[str_size] = '\0' : str[str_size-2]++ , str[str_size-1] = '0' ) ) : ( str[str_size-1]++ ) ) ) ( printf("Trying %s:",str) , (strcmp(qux(baz(str)) , str) == 0) ? ( printf(" pass\n") , NULL ) : ( printf(" FAIL, got %s\n",qux(baz(str))) , errors_size++ , errors = realloc(errors, sizeof(*errors)*errors_size ) , errors[errors_size-1] = malloc( sizeof(*str)*(str_size+1) ) , memcpy(errors[errors_size-1] , str , sizeof(*str)*(str_size+1)) ) );
    for ( ( printf("\n\nERROR SUMMARY:\n\nTried %d cases. %d errors found (%f%%)\n\n",i,errors_size,100.0*(((float)errors_size)/((float)i))) , i = 0 ) ; i < ( (errors_size < 100) ? errors_size : 1) ; i++ ) ( (errors_size < 100) ? (printf("%d.\t%s\t-->   %s\n",i,errors[i],qux(baz(errors[i])))) : ( printf("The amount of cases to show is too big.\n") ) );
    return 0; }

这只有 7 行代码,主要部分仅在其中两行中执行。我尝试构建一串以'1' 开头的字符,并为每一步递增。但是,当我达到 999 之类的数字时,我必须将其全部设置为零并在开头添加 1。我能想到的唯一方法是使用 for 循环。

一种可能的解决方案是创建一个函数来增加str,但这意味着要编写额外的代码行,这不是我所面临挑战的最佳解决方案。

【问题讨论】:

  • for 循环不在括号内。它们是语句,不能在表达式中使用。删除 for 循环周围的括号。如果, bar() 应该是独立的,而不是for 的一部分,则将其设为; bar();
  • 嗯,这正是我的问题所在。在我自己的 C 代码中,我需要在顺序评估中包含一个 for 循环,否则我将不得不全部重写。有没有办法做到这一点?即使不使用 for 循环本身,而是使用替代解决方案来保持顺序评估结构完整?
  • 请说明您打算将bar 放在循环内部还是外部
  • 如果你想尽量减少代码行,只需将所有语句放在一行。 C 中没有规定分号后面必须跟换行符。
  • 代码高尔夫和混淆并不是这个网站的最佳选择。此类问题应在Code golf 提出。 “与解决编程难题或特定类型的挑战相关的非挑战问题也是主题。”

标签: c for-loop comma-operator


【解决方案1】:

您的实际代码中可能缺少分号,但在语句中使用逗号运算符是完全可以的,例如:

for(int i = 0; i < 10; i++) printf("%d", i), printf(" Hello\n");

【讨论】:

  • 不,我的意思是:我在这里进行顺序评估。所以你的代码是:( for(int i = 0; i &lt; 10; i++) printf("%d", i) , printf(" Hello\n") );,它不能编译。 (正如我在问题中指出的那样,我得到了error: expected expression)。
  • “顺序评估”是什么意思?你为什么在我的代码中的 for 语句周围加上括号?
  • 您可以阅读顺序评估运算符here 的行为描述。根据它,这将是编写代码的方式(使用顺序评估)。
【解决方案2】:

您只能在表达式周围加上括号。
关键字结构,如 for 不计为表达式。

正如@mnistic 所建议的,你可以这样写:

for(initialization;condition;increment) foo() , bar();

没有最外面的括号。

但你不能在 for 循环周围放置括号。

这样做有什么问题?

for(initialization;condition;increment) foo();
bar();

为什么你需要使用逗号?

【讨论】:

  • 那么,是否有另一种方法可以在顺序评估中执行 for 循环?还是根本不可能?
【解决方案3】:

你在这里想太多了。语句是按顺序评估的,因此根据您的示例,您可以按以下方式执行:

for(initialization;condition;increment) 
    foo();
bar();

如果对bar 的调用是某个更大表达式的一部分,那么该表达式会出现在bar(); 上方的位置,而for 循环位于其之前。

如果这仍然不是您想要的,那么您需要向我们提供更多关于您正在做什么以及为什么您认为需要像您提议的那样的构造的背景信息。

【讨论】:

  • 我刚刚更新了我的问题以提供更多背景信息。
【解决方案4】:

这篇文章的许多很好的答案都涵盖了语句和表达式之间的区别。想强调几个可以实现将 for 语句转换为表达式的替代方法。

一些注意事项:

这不是标准的“C” - 它使用的是 GCC 扩展。。如果构建要求严格符合标准,您可能必须在构建中启用它们。

OP没有提供具体案例,所以很难判断是否有其他具体的替代方案

选项 1 - 作为表达式的语句

见:https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html#Statement-Exprs

int func(void)
{
    // Execute the loop as expression
    ({ for (...) foo()  ; bar() }) ;
}

选项 2 - 使用嵌套函数

见:https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html#Nested-Functions

int func(void)
{
    void foo_loop(void) {
        for (...) foo() ;
    }

    // Execute the loop as expression
    ( foo_loop(), bar() ) ;
}

嵌套函数 foo_loop 可以访问局部变量。

选项 3 - 使用函数调用

OP 不清楚循环依赖项是什么。如果它很简单(例如,循环 N 次),可以使用辅助函数

void foo_loop(int n) {
     for (int i=0 ; i<n ; i++) foo() ;
}

int func(void)
{
    // Execute the loop in the function
    int n = 50 ;
    ( foo_loop(n), bar() ) ;
}

【讨论】:

  • 感谢您的回答!它确实提供了一个解决方案,但遗憾的是不是我正在寻找的那个。但是,我想我最好的选择是尝试编写一个辅助函数来执行 for 循环,正如您所建议的那样。
猜你喜欢
  • 1970-01-01
  • 2011-12-17
  • 2014-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-07
  • 2018-03-24
相关资源
最近更新 更多