Joh*_*itb 190
C没有foreach,但宏经常用于模拟:
#define for_each_item(item, list) \
for(T * item = list->head; item != NULL; item = item->next)
Run Code Online (Sandbox Code Playgroud)
并且可以像
for_each_item(i, processes) {
i->wakeup();
}
Run Code Online (Sandbox Code Playgroud)
也可以在数组上进行迭代:
#define foreach(item, array) \
for(int keep = 1, \
count = 0,\
size = sizeof (array) / sizeof *(array); \
keep && count != size; \
keep = !keep, count++) \
for(item = (array) + count; keep; keep = !keep)
Run Code Online (Sandbox Code Playgroud)
并且可以像
int values[] = { 1, 2, 3 };
foreach(int *v, values) {
printf("value: %d\n", *v);
}
Run Code Online (Sandbox Code Playgroud)
编辑:如果您对C++解决方案也感兴趣,C++有一个原生的for-each语法,称为"基于范围"
Jud*_*den 11
这是C99中for-each宏的完整程序示例:
#include <stdio.h>
typedef struct list_node list_node;
struct list_node {
list_node *next;
void *data;
};
#define FOR_EACH(item, list) \
for (list_node *(item) = (list); (item); (item) = (item)->next)
int
main(int argc, char *argv[])
{
list_node list[] = {
{ .next = &list[1], .data = "test 1" },
{ .next = &list[2], .data = "test 2" },
{ .next = NULL, .data = "test 3" }
};
FOR_EACH(item, list)
puts((char *) item->data);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
C中没有foreach.
您可以使用for循环来遍历数据,但需要知道长度或者需要通过已知值(例如,null)终止数据.
char* nullTerm;
nullTerm = "Loop through my characters";
for(;nullTerm != NULL;nullTerm++)
{
//nullTerm will now point to the next character.
}
Run Code Online (Sandbox Code Playgroud)
虽然 C 没有 for every 构造,但它总是有一个惯用的表示形式来表示数组末尾的一个(&arr)[1]
。这允许您为每个循环编写一个简单的惯用语,如下所示:
int arr[] = {1,2,3,4,5};
for(int *a = arr; a < (&arr)[1]; ++a)
printf("%d\n", *a);
Run Code Online (Sandbox Code Playgroud)
这是一个相当古老的问题,但我应该发布这个问题.它是GNU C99的foreach循环.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define FOREACH_COMP(INDEX, ARRAY, ARRAY_TYPE, SIZE) \
__extension__ \
({ \
bool ret = 0; \
if (__builtin_types_compatible_p (const char*, ARRAY_TYPE)) \
ret = INDEX < strlen ((const char*)ARRAY); \
else \
ret = INDEX < SIZE; \
ret; \
})
#define FOREACH_ELEM(INDEX, ARRAY, TYPE) \
__extension__ \
({ \
TYPE *tmp_array_ = ARRAY; \
&tmp_array_[INDEX]; \
})
#define FOREACH(VAR, ARRAY) \
for (void *array_ = (void*)(ARRAY); array_; array_ = 0) \
for (size_t i_ = 0; i_ && array_ && FOREACH_COMP (i_, array_, \
__typeof__ (ARRAY), \
sizeof (ARRAY) / sizeof ((ARRAY)[0])); \
i_++) \
for (bool b_ = 1; b_; (b_) ? array_ = 0 : 0, b_ = 0) \
for (VAR = FOREACH_ELEM (i_, array_, __typeof__ ((ARRAY)[0])); b_; b_ = 0)
/* example's */
int
main (int argc, char **argv)
{
int array[10];
/* initialize the array */
int i = 0;
FOREACH (int *x, array)
{
*x = i;
++i;
}
char *str = "hello, world!";
FOREACH (char *c, str)
printf ("%c\n", *c);
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
此代码已经过测试,可以在GNU/Linux上使用gcc,icc和clang.
您可能已经知道,C中没有“ foreach”样式的循环。
尽管这里已经提供了许多出色的宏来解决此问题,但也许您会发现此宏很有用:
// "length" is the length of the array.
#define each(item, array, length) \
(typeof(*(array)) *p = (array), (item) = *p; p < &((array)[length]); p++, (item) = *p)
Run Code Online (Sandbox Code Playgroud)
...可与使用for
(如在for each (...)
)。
这种方法的优点:
item
在for语句中声明并递增(就像在Python中一样!)。p
,item
)中创建的所有变量在循环范围之外都不可见(因为它们是在for循环头中声明的)。缺点:
typeof()
,它是gcc扩展,不是标准C的一部分为了节省您的时间,下面是测试方法:
typedef struct _point {
double x;
double y;
} Point;
int main(void)
{
double some_nums[] = {4.2, 4.32, -9.9, 7.0};
for each (element, some_nums, 4)
printf("element = %lf\n", element);
int numbers[] = {4, 2, 99, -3, 54};
// Just demonstrating it can be used like a normal for loop
for each (number, numbers, 5) {
printf("number = %d\n", number);
if (number % 2 == 0)
printf("%d is even.\n", number);
}
char *dictionary[] = {"Hello", "World"};
for each (word, dictionary, 2)
printf("word = '%s'\n", word);
Point points[] = {{3.4, 4.2}, {9.9, 6.7}, {-9.8, 7.0}};
for each (point, points, 3)
printf("point = (%lf, %lf)\n", point.x, point.y);
// Neither p, element, number or word are visible outside the scope of
// their respective for loops. Try to see if these printfs work
// (they shouldn't):
// printf("*p = %s", *p);
// printf("word = %s", word);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它似乎可以在gcc和clang上工作;不确定其他编译器。