[c] C에 “foreach”루프 구조가 있습니까?

거의 모든 언어에는 foreach루프 또는 이와 유사한 것이 있습니다. C에 하나가 있습니까? 예제 코드를 게시 할 수 있습니까?



답변

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 구문이 있습니다.


답변

다음은 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;
}


답변

C에는 foreach가 없습니다.

for 루프를 사용하여 데이터를 반복 할 수 있지만 길이를 알고 있거나 데이터를 알고있는 값 (예 : null)으로 종료해야합니다.

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

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


답변

이미 알고 계시 겠지만 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 에서처럼!).
  • 모든 1 차원 배열에서 작동하는 것 같습니다.
  • 매크로 ( p, item) 에서 생성 된 모든 변수 는 루프 범위 밖에서 보이지 않습니다 (for 루프 헤더에서 선언 되었기 때문에).

단점 :

  • 다차원 배열에서는 작동하지 않습니다.
  • typeof()GNU 확장이 아닌 에 의존합니다 .표준 C의 일부가
  • for 루프 헤더에서 변수를 선언하므로 C11 이상에서만 작동합니다.

시간을 절약하기 위해 다음과 같이 테스트 할 수 있습니다.

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

기본적으로 gcc 및 clang에서 작동하는 것 같습니다. 다른 컴파일러를 테스트하지 않았습니다.


답변

이것은 상당히 오래된 질문이지만 나는 이것을 게시해야합니다. 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;
}

이 코드는 GNU / Linux에서 gcc, icc 및 clang과 함께 작동하도록 테스트되었습니다.


답변

C에는 각 구성에 대한 a가 없지만 항상 배열의 끝을 지나서 하나에 대한 관용적 표현이 (&arr)[1]있습니다. 이를 통해 다음과 같이 각 루프에 대한 간단한 관용어를 작성할 수 있습니다.

int arr[] = {1,2,3,4,5};
for(int *a = arr; a < (&arr)[1]; ++a)
    printf("%d\n", *a);


답변

C에는 ‘for’및 ‘while’키워드가 있습니다. C #과 같은 언어의 foreach 문이 다음과 같은 경우 …

foreach (Element element in collection)
{
}

… C에서이 foreach 문에 해당하는 내용은 다음과 같습니다.

for (
    Element* element = GetFirstElement(&collection);
    element != 0;
    element = GetNextElement(&collection, element)
    )
{
    //TODO: do something with this element instance ...
}