Presque toutes les langues ont une boucle foreach
ou quelque chose de similaire. Est-ce que C en a un? Pouvez-vous poster un exemple de code?
C n’a pas de foreach, mais les macros sont fréquemment utilisées pour émuler cela:
#define for_each_item(item, list) \ for(T * item = list->head; item != NULL; item = item->next)
Et peut être utilisé comme
for_each_item(i, processes) { i->wakeup(); }
L’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é comme
int values[] = { 1, 2, 3 }; foreach(int *v, values) { printf("value: %d\n", *v); }
Edit: Au cas où vous vous intéressez aussi aux solutions C ++, C ++ possède une syntaxe native pour-chaque appelée “range based for”
Voici un exemple de programme complet d’une macro for-each dans C99:
#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; }
Il n’y a pas de foreach dans 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. }
C’est une question assez ancienne, mais je pense que je devrais poster ceci. C’est une boucle foreach pour GNU C99.
#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; }
Ce code a été testé pour fonctionner avec gcc, icc et clang sur GNU / Linux.
Comme vous le savez probablement déjà, il n’y a pas de boucle de style “foreach” dans C.
Bien qu’il y ait déjà des tonnes de macros géniales pour contourner ce problème, vous trouverez peut-être cette macro utile.
// "length" is the length of the array. #define each(item, array, length) \ (typeof(*(array)) *p = (array), (item) = *p; p < &((array)[length]); p++, (item) = *p)
... qui peut être utilisé avec for
(comme for each (...)
).
Avantages de cette approche:
item
est déclaré et incrémenté dans l'instruction for (comme dans Python!). p
, item
) ne sont pas visibles en dehors de la scope de la boucle (car elles sont déclarées dans l'en-tête de la boucle for). Désavantages:
typeof()
, qui est une extension gcc; NE fait PAS partie de la norme C Juste pour vous faire gagner du temps, voici comment vous pouvez le tester:
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; }
Semble travailler sur gcc et clang; pas sûr des autres compilateurs.
Alors que C n’a pas de pour chaque construction, il a toujours eu une représentation idiomatique pour un passé après un tableau (&arr)[1]
. Cela vous permet d’écrire un idiomatique simple pour chaque boucle comme suit:
int arr[] = {1,2,3,4,5}; for(int *a = arr; a < (&arr)[1]; ++a) printf("%d\n", *a);
C a les mots-clés ‘for’ et ‘while’. Si une instruction foreach dans un langage comme C # ressemble à ceci …
foreach (Element element in collection) { }
… alors l’équivalent de cette instruction foreach en C pourrait être:
for ( Element* element = GetFirstElement(&collection); element != 0; element = GetNextElement(&collection, element) ) { //TODO: do something with this element instance ... }
La réponse d’Eric ne fonctionne pas lorsque vous utilisez “break” ou “continue”.
Cela peut être corrigé en réécrivant la première ligne:
Ligne originale (reformatée):
for (unsigned i = 0, __a = 1; i < B.size(); i++, __a = 1)
Fixé:
for (unsigned i = 0, __a = 1; __a && i < B.size(); i++, __a = 1)
Si vous le comparez à la boucle de Johannes, vous verrez qu'il fait la même chose, juste un peu plus compliqué et plus laid.
Voici un simple, simple pour la boucle:
#define FOREACH(type, array, size) do { \ type it = array[0]; \ for(int i = 0; i < size; i++, it = array[i]) #define ENDFOR } while(0); int array[] = { 1, 2, 3, 4, 5 }; FOREACH(int, array, 5) { printf("element: %d. index: %d\n", it, i); } ENDFOR
Vous donne access à l'index si vous le souhaitez ( i
) et à l'élément actuel que nous parcourons ( it
). Notez que vous pouvez avoir des problèmes de dénomination lors de l'imbrication des boucles, vous pouvez faire en sorte que les noms d'éléments et d'index soient des parameters pour la macro.
Edit: Voici une version modifiée de la réponse acceptée. Vous permet de spécifier l'index de start
, la size
pour qu'il fonctionne sur les tableaux dégradés (pointeurs), pas besoin de int*
et de count != size
to i < size
juste au cas où l'utilisateur modifie accidentellement "i" et se coincer dans une boucle infinie.
#define FOREACH(item, array, start, size)\ for(int i = start, keep = 1;\ keep && i < size;\ keep = !keep, i++)\ for (item = array[i]; keep; keep = !keep) int array[] = { 1, 2, 3, 4, 5 }; FOREACH(int x, array, 2, 5) printf("index: %d. element: %d\n", i, x);
Sortie:
index: 2. element: 3 index: 3. element: 4 index: 4. element: 5
Voici ce que j’utilise quand je suis coincé avec C. Vous ne pouvez pas utiliser le même nom d’élément deux fois dans la même scope, mais ce n’est pas vraiment un problème puisque nous n’utilisons pas tous de nouveaux compilateurs sympas 🙁
#define FOREACH(type, item, array, size) \ size_t X(keep), X(i); \ type item; \ for (X(keep) = 1, X(i) = 0 ; X(i) < (size); X(keep) = !X(keep), X(i)++) \ for (item = (array)[X(i)]; X(keep); X(keep) = 0) #define _foreach(item, array) FOREACH(__typeof__(array[0]), item, array, length(array)) #define foreach(item_in_array) _foreach(item_in_array) #define in , #define length(array) (sizeof(array) / sizeof((array)[0])) #define CAT(a, b) CAT_HELPER(a, b) /* Concatenate two symbols for macros! */ #define CAT_HELPER(a, b) a ## b #define X(name) CAT(__##name, __LINE__) /* unique variable */
Usage:
int ints[] = {1, 2, 0, 3, 4}; foreach (i in ints) printf("%i", i); /* can't use the same name in this scope anymore! */ foreach (x in ints) printf("%i", x);
Si vous prévoyez de travailler avec des pointeurs de fonction
#define lambda(return_type, function_body)\ ({ return_type __fn__ function_body __fn__; }) #define array_len(arr) (sizeof(arr)/sizeof(arr[0])) #define foreachnf(type, item, arr, arr_length, func) {\ void (*action)(type item) = func;\ for (int i = 0; i
Usage:
int ints[] = { 1, 2, 3, 4, 5 }; foreach(int, i, ints, { printf("%d\n", i); }); char* strs[] = { "hi!", "hello!!", "hello world", "just", "testing" }; foreach(char*, s, strs, { printf("%s\n", s); }); char** strsp = malloc(sizeof(char*)*2); strsp[0] = "abcd"; strsp[1] = "efgh"; foreachn(char*, s, strsp, 2, { printf("%s\n", s); }); void (*myfun)(int i) = somefunc; foreachf(int, i, ints, myfun);
Mais je pense que cela ne fonctionnera que sur gcc (pas sûr).
C n’a pas d’implémentation de for-each
. Lors de l’parsing d’un tableau en tant que point, le récepteur ne sait pas combien de temps le tableau est, il n’y a donc aucun moyen de savoir quand vous atteignez la fin du tableau. Rappelez-vous, dans C int*
est un point sur une adresse mémoire contenant un int. Il n’y a pas d’object d’en-tête contenant des informations sur le nombre d’entiers placés dans l’ordre. Ainsi, le programmeur doit en garder la trace.
Cependant, pour les listes, il est facile d’implémenter quelque chose qui ressemble à une boucle for-each
.
for(Node* node = head; node; node = node.next) { /* do your magic here */ }
Pour obtenir quelque chose de similaire pour les tableaux, vous pouvez faire l’une des deux choses suivantes.
Voici un exemple d’une telle structure:
typedef struct job_t { int count; int* arr; } arr_t;