C имеет “foreach” конструкцию цикла?

Предупреждение: недопустимое смещение строки 'XXX'

Это происходит, когда вы пытаетесь получить доступ к элементу массива с синтаксисом с квадратной скобкой, но вы делаете это по строке, а не по массиву, поэтому операция явно не имеет смысла .

Пример:

$var = "test";
echo $var["a_key"];

Если вы считаете, что переменная должна быть массивом, см., где она появляется и исправить там проблему.

103
задан MD XF 19 May 2017 в 01:46
поделиться

5 ответов

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++ имеет собственный компонент для - каждый синтаксис, названный "диапазон, базирующийся для"

188
ответ дан Johannes Schaub - litb 24 November 2019 в 04:17
поделиться

Вот полный пример программы для - каждый макрос в 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;
}
11
ответ дан Judge Maygarden 24 November 2019 в 04:17
поделиться

В C нет никакого foreach.

можно использовать для цикла для цикличного выполнения через данные, но длина должна быть, знают, или данные должны быть завершены знать значением (например, пустой указатель).

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

for(;nullTerm != NULL;nullTerm++)
{
    //nullTerm will now point to the next character.
}
9
ответ дан Adam Peck 24 November 2019 в 04:17
поделиться

C имеет 'для' и 'в то время как' ключевые слова. Если foreach оператор на языке как C# похож на это...

foreach (Element element in collection)
{
}

... тогда эквивалент этого foreach оператора в C мог бы быть быть похожим:

for (
    Element* element = GetFirstElement(&collection);
    element != 0;
    element = GetNextElement(&collection, element)
    )
{
    //TODO: do something with this element instance ...
}
2
ответ дан ChrisW 24 November 2019 в 04:17
поделиться

Это довольно старый вопрос, но я решил, что должен его опубликовать. Это цикл foreach для 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;
}

Этот код был протестирован для работы с gcc, icc и clang в GNU / Linux.

5
ответ дан 24 November 2019 в 04:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: