在 c 中的顺序评估中执行 for 循环
Doing a for loop in a sequential evaluation in c
我正在尝试在 C 中使用顺序求值运算符 (,
),并且我想在第一个表达式中执行 for 循环,如下所示:
( for(initialization;condition;increment) foo() , bar() )
但是写那一行我得到一个 error: expected expression
.
如果我发现这是不可能的事情,我不会感到惊讶,尽管让我犹豫的是我可以以 logical_expression ? expression_true : expression_false
.[=27 的形式执行伪 if 语句=]
有什么办法吗?或者我需要在外部创建 for 循环吗?
编辑:
我决定更新我的问题以提供有关我的问题的更多背景信息。
我有两个函数,我们称它们为 baz()
和 qux()
。 qux()
是 baz()
的反函数,因此对于任何给定的输入,qux(baz(input))
应该 return 输入。
具体来说,baz()
接受一个字符数组,所有字符都在 '0'
和 '9'
之间,而 returns 是该数字的另一种格式表示与这个问题无关。当我们将不同的表示传递给 quz()
时,我们得到了原始数组。
所以我想构建自己的代码来测试任意数量的案例,看看 qux(baz(input))
是否是 return 想要的结果。而且我想在 尽可能少的代码行中做到这一点 (只是将所有行放在同一行中,用分号分隔,这不是我想要的)。
我知道我可以使用像 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] = '[=11=]');
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] = '[=11=]' : 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(int i = 0; i < 10; i++) printf("%d", i), printf(" Hello\n");
您只能在 表达式 周围放置括号。
关键字构造,如 for
不算作表达式。
正如@mnistic 所建议的,您可以这样写:
for(initialization;condition;increment) foo() , bar();
没有最外层的括号。
但是你不能将括号放在 for
循环周围。
这样做有什么问题吗?
for(initialization;condition;increment) foo();
bar();
为什么需要使用逗号?
你想多了。语句是按顺序计算的,因此根据您的示例,您可以按如下方式进行:
for(initialization;condition;increment)
foo();
bar();
如果对 bar
的调用是某个较大表达式的一部分,则该表达式位于 bar();
上方,而 for
循环位于其之前。
如果这仍然不是您想要的,那么您需要向我们提供更多关于您正在做的事情的背景信息,以及为什么您认为您需要像您提议的那样的结构。
语句和表达式之间的区别已包含在对此 post 的许多好的答案中。想要强调几个替代方案,它们将实现相当于将 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() ) ;
}
我正在尝试在 C 中使用顺序求值运算符 (,
),并且我想在第一个表达式中执行 for 循环,如下所示:
( for(initialization;condition;increment) foo() , bar() )
但是写那一行我得到一个 error: expected expression
.
如果我发现这是不可能的事情,我不会感到惊讶,尽管让我犹豫的是我可以以 logical_expression ? expression_true : expression_false
.[=27 的形式执行伪 if 语句=]
有什么办法吗?或者我需要在外部创建 for 循环吗?
编辑:
我决定更新我的问题以提供有关我的问题的更多背景信息。
我有两个函数,我们称它们为 baz()
和 qux()
。 qux()
是 baz()
的反函数,因此对于任何给定的输入,qux(baz(input))
应该 return 输入。
具体来说,baz()
接受一个字符数组,所有字符都在 '0'
和 '9'
之间,而 returns 是该数字的另一种格式表示与这个问题无关。当我们将不同的表示传递给 quz()
时,我们得到了原始数组。
所以我想构建自己的代码来测试任意数量的案例,看看 qux(baz(input))
是否是 return 想要的结果。而且我想在 尽可能少的代码行中做到这一点 (只是将所有行放在同一行中,用分号分隔,这不是我想要的)。
我知道我可以使用像 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] = '[=11=]');
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] = '[=11=]' : 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(int i = 0; i < 10; i++) printf("%d", i), printf(" Hello\n");
您只能在 表达式 周围放置括号。
关键字构造,如 for
不算作表达式。
正如@mnistic 所建议的,您可以这样写:
for(initialization;condition;increment) foo() , bar();
没有最外层的括号。
但是你不能将括号放在 for
循环周围。
这样做有什么问题吗?
for(initialization;condition;increment) foo();
bar();
为什么需要使用逗号?
你想多了。语句是按顺序计算的,因此根据您的示例,您可以按如下方式进行:
for(initialization;condition;increment)
foo();
bar();
如果对 bar
的调用是某个较大表达式的一部分,则该表达式位于 bar();
上方,而 for
循环位于其之前。
如果这仍然不是您想要的,那么您需要向我们提供更多关于您正在做的事情的背景信息,以及为什么您认为您需要像您提议的那样的结构。
语句和表达式之间的区别已包含在对此 post 的许多好的答案中。想要强调几个替代方案,它们将实现相当于将 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() ) ;
}