当前位置:  开发笔记 > 编程语言 > 正文

C是否有"foreach"循环结构?

如何解决《C是否有"foreach"循环结构?》经验,为你挑选了5个好方法。

几乎所有语言都有一个foreach循环或类似的东西.C有一个吗?你能发布一些示例代码吗?



1> Johannes Sch..:

C没有foreach,但宏经常用于模拟:

#define for_each_item(item, list) \
    for(T * item = list->head; item != NULL; item = item->next)

并且可以像

for_each_item(i, processes) {
    i->wakeup();
}

也可以在数组上进行迭代:

#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)

并且可以像

int values[] = { 1, 2, 3 };
foreach(int *v, values) {
    printf("value: %d\n", *v);
}

编辑:如果您对C++解决方案也感兴趣,C++有一个原生的for-each语法,称为"基于范围"


@eSKay是的,考虑`if(...)foreach(int*v,values)...`.如果它们在循环之外,它会扩展为`if(...)int count = 0 ...; for(...)...;`并且会打破.

2> Judge Maygar..:

这是C99中for-each宏的完整程序示例:

#include 

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;
}


@Rizo不,点是_C99指定initializers_语法的一部分.请参见http://en.wikipedia.org/wiki/C_syntax#Initialization
@Judge:好吧,一方面,它具有“令人惊讶的”生命周期(如果您正在使用删除元素的代码,则很可能会崩溃在“ free()”中),另一方面,它具有对内部值的引用它的定义。这确实是一个太愚蠢的事的例子。代码足够复杂,而没有故意添加聪明之处。Kernighan的格言(http://stackoverflow.com/questions/1103299/help-me-understand-this-brian-kernighan-quote)适用!

3> Adam Peck..:

C中没有foreach.

您可以使用for循环来遍历数据,但需要知道长度或者需要通过已知值(例如,null)终止数据.

char* nullTerm;
nullTerm = "Loop through my characters";

for(;nullTerm != NULL;nullTerm++)
{
    //nullTerm will now point to the next character.
}



4> Joe D..:

这是一个相当古老的问题,但我应该发布这个问题.它是GNU C99的foreach循环.

#include 
#include 
#include 
#include 

#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;
}

此代码已经过测试,可以在GNU/Linux上使用gcc,icc和clang.



5> Saeed Baig..:

您可能已经知道,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)

...可与使用for(如在for each (...))。

这种方法的优点:

item 在for语句中声明并递增(就像在Python中一样!)。

似乎可以在任何一维数组上工作

在宏(pitem)中创建的所有变量在循环范围之外都不可见(因为它们是在for循环头中声明的)。

缺点:

对多维数组不起作用

依赖于typeof(),它是gcc扩展,不是标准C的一部分

由于它在for循环头中声明了变量,因此仅在C11或更高版本中有效。

为了节省您的时间,下面是测试方法:

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;
}

它似乎可以在gcc和clang上工作;不确定其他编译器。

推荐阅读
php
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有