Casi todos los idiomas tienen un foreach
bucle o algo similar. ¿C tiene uno? ¿Puedes publicar algún código de ejemplo?
foreach
bucle en un programa en C?
Casi todos los idiomas tienen un foreach
bucle o algo similar. ¿C tiene uno? ¿Puedes publicar algún código de ejemplo?
foreach
bucle en un programa en C?
Respuestas:
C no tiene un foreach, pero las macros se usan con frecuencia para emular eso:
#define for_each_item(item, list) \
for(T * item = list->head; item != NULL; item = item->next)
Y se puede usar como
for_each_item(i, processes) {
i->wakeup();
}
La iteración sobre una matriz también es posible:
#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)
Y se puede usar como
int values[] = { 1, 2, 3 };
foreach(int *v, values) {
printf("value: %d\n", *v);
}
Editar: en caso de que también esté interesado en las soluciones de C ++, C ++ tiene una sintaxis nativa para cada llamada llamada "rango basado en"
#define foreach(item, array) int count=0, size=sizeof(array)/sizeof(*(array)); for(item = (array); count != size; count++, item = (array)+count)
Un problema que puedo ver es que las variables cuentan y tamaño viven fuera del ciclo for y pueden causar un conflicto. ¿Es esta la razón por la que usa dos bucles for? [código pegado aquí ( pastebin.com/immndpwS )]
if(...) foreach(int *v, values) ...
. Si están fuera del bucle, se expande if(...) int count = 0 ...; for(...) ...;
y se rompe.
A continuación se muestra un ejemplo de programa completo de una macro para cada en 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;
}
list[]
definición? ¿No podrías simplemente escribir en next
lugar de .next
?
free()
) y por otro tiene una referencia al valor dentro de su definición. Es realmente un ejemplo de algo que es demasiado inteligente; el código es lo suficientemente complejo sin agregarle inteligencia a propósito. ¡Se aplica el aforismo de Kernighan ( stackoverflow.com/questions/1103299/… )!
No hay foreach en C.
Puede usar un bucle for para recorrer los datos, pero se debe conocer la longitud o los datos deben terminarse con un valor conocido (por ejemplo, nulo).
char* nullTerm;
nullTerm = "Loop through my characters";
for(;nullTerm != NULL;nullTerm++)
{
//nullTerm will now point to the next character.
}
Como probablemente ya sepa, no hay un bucle de estilo "foreach" en C.
Aunque ya hay toneladas de macros geniales proporcionadas aquí para solucionar esto, tal vez encuentre útil esta macro:
// "length" is the length of the array.
#define each(item, array, length) \
(typeof(*(array)) *p = (array), (item) = *p; p < &((array)[length]); p++, (item) = *p)
... que se puede usar con for
(como en for each (...)
).
Ventajas de este enfoque:
item
se declara y se incrementa dentro de la declaración for (¡como en Python!).p
, item
) no son visibles fuera del alcance del bucle (ya que están declaradas en el encabezado del bucle for).Desventajas:
typeof()
, que es una extensión GNU, no parte del estándar CSolo para ahorrarle algo de tiempo, así es como puede probarlo:
typedef struct {
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;
}
Parece funcionar en gcc y clang de forma predeterminada; no he probado otros compiladores.
Esta es una pregunta bastante antigua, pero pensé que debería publicar esto. Es un bucle foreach para 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;
}
Este código ha sido probado para funcionar con gcc, icc y clang en GNU / Linux.
Si bien C no tiene una para cada construcción, siempre ha tenido una representación idiomática para una más allá del final de una matriz (&arr)[1]
. Esto le permite escribir un modismo simple para cada bucle de la siguiente manera:
int arr[] = {1,2,3,4,5};
for(int *a = arr; a < (&arr)[1]; ++a)
printf("%d\n", *a);
(&arr)[1]
no significa un elemento de la matriz más allá del final de la matriz, significa una matriz más allá del final de la matriz. (&arr)[1]
no es el último elemento de la matriz [0], es la matriz [1], que decae en un puntero al primer elemento (de la matriz [1]). Creo que sería mucho mejor, más seguro e idiomático hacerlo const int* begin = arr; const int* end = arr + sizeof(arr)/sizeof(*arr);
y luego for(const int* a = begin; a != end; a++)
.
C tiene palabras clave "para" y "mientras". Si una declaración foreach en un lenguaje como C # se ve así ...
foreach (Element element in collection)
{
}
... entonces el equivalente de esta declaración foreach en C podría ser como:
for (
Element* element = GetFirstElement(&collection);
element != 0;
element = GetNextElement(&collection, element)
)
{
//TODO: do something with this element instance ...
}
Esto es lo que uso cuando estoy atascado con C. No puede usar el mismo nombre de elemento dos veces en el mismo alcance, pero eso no es realmente un problema ya que no todos podemos usar compiladores nuevos y agradables :(
#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 */
Uso:
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);
EDITAR: Aquí hay una alternativa para FOREACH
usar la sintaxis c99 para evitar la contaminación del espacio de nombres:
#define FOREACH(type, item, array, size) \
for (size_t X(keep) = 1, X(i) = 0; X(i) < (size); X(keep) = 1, X(i)++) \
for (type item = (array)[X(i)]; X(keep); X(keep) = 0)
VAR(i) < (size) && (item = array[VAR(i)])
se detendría una vez que el elemento de la matriz tuviera un valor de 0. Por lo tanto, usar esto con double Array[]
puede no iterar a través de todos los elementos. Parece que la prueba de bucle debería ser una u otra: i<n
o A[i]
. Tal vez agregue casos de uso de muestra para mayor claridad.
if ( bla ) FOREACH(....) { } else....
FOREACH
que usa la sintaxis c99 para evitar la contaminación del espacio de nombres.
La respuesta de Eric no funciona cuando usa "romper" o "continuar".
Esto se puede solucionar reescribiendo la primera línea:
Línea original (reformateada):
for (unsigned i = 0, __a = 1; i < B.size(); i++, __a = 1)
Fijo:
for (unsigned i = 0, __a = 1; __a && i < B.size(); i++, __a = 1)
Si lo comparas con el bucle de Johannes, verás que en realidad él está haciendo lo mismo, solo que un poco más complicado y feo.
Aquí hay uno simple, single for loop:
#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
Le da acceso al índice si lo desea ( i
) y al elemento actual sobre el que estamos iterando ( it
). Tenga en cuenta que puede tener problemas de nomenclatura al anidar bucles, puede hacer que los nombres de los elementos y los índices sean parámetros de la macro.
Editar: aquí hay una versión modificada de la respuesta aceptada foreach
. Le permite especificar el start
índice, size
para que funcione en matrices deterioradas (punteros), sin necesidad int*
y cambiado count != size
a i < size
solo en caso de que el usuario modifique accidentalmente 'i' para que sea más grande que size
y se quede atascado en un bucle infinito.
#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);
Salida:
index: 2. element: 3
index: 3. element: 4
index: 4. element: 5
Si planea trabajar con punteros de función
#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<arr_length; i++) action(arr[i]);\
}
#define foreachf(type, item, arr, func)\
foreachnf(type, item, arr, array_len(arr), func)
#define foreachn(type, item, arr, arr_length, body)\
foreachnf(type, item, arr, arr_length, lambda(void, (type item) body))
#define foreach(type, item, arr, body)\
foreachn(type, item, arr, array_len(arr), body)
Uso:
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);
Pero creo que esto solo funcionará en gcc (no estoy seguro).
C no tiene una implementación de for-each
. Al analizar una matriz como un punto, el receptor no sabe cuánto dura la matriz, por lo que no hay forma de saber cuándo llega al final de la matriz. Recuerda, en Cint*
hay un punto a una dirección de memoria que contiene un int. No hay ningún objeto de encabezado que contenga información sobre cuántos enteros se colocan en secuencia. Por lo tanto, el programador debe realizar un seguimiento de esto.
Sin embargo, para las listas, es fácil implementar algo que se parezca a un for-each
bucle.
for(Node* node = head; node; node = node.next) {
/* do your magic here */
}
Para lograr algo similar para las matrices, puede hacer una de dos cosas.
El siguiente es un ejemplo de tal estructura:
typedef struct job_t {
int count;
int* arr;
} arr_t;
foreach
" ¿de qué?