115 votes

Est-ce que C a une construction de boucle "foreach"?

Presque toutes les langues ont une boucle foreach (fonction) ou quelque chose de similaire. Je me demande si C en a un? Pouvez-vous poster un exemple de code?

205voto

C n'est pas un foreach, mais les macros sont fréquemment utilisés pour imiter que:

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

Et peut être utilisée comme

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

Itération sur un tableau est également possible:

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

Et peut être utilisée comme

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

Edit: Dans le cas où vous sont également intéressés en C++ solutions, boost (mais le C++ lui-même n'a pas un natif pour chaque boucle encore): coup de pouce.ForEach

33voto

chaos Points 69029
En elle-même, non.

11voto

Judge Maygarden Points 14964

Voici un exemple de programme complet d'une macro for-each dans C99:

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

9voto

Adam Peck Points 3000

Il n'y a pas de foreach en C.

Vous pouvez utiliser une boucle for pour parcourir les données, mais la longueur doit être connue ou les données doivent être terminées par une valeur connue (par exemple, null).

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

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

5voto

Joe D Points 1545

C'est une question assez ancienne, mais je pensais que je devrais poster ceci. C'est une boucle foreach pour GNU C99.

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

Ce code a été testé pour fonctionner avec gcc, icc et clang sous GNU / Linux.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X