Последние сообщения

Страницы: [1] 2 3 ... 10
1
Общий раздел / Re: ещё про цикл дейкстры
« Последний ответ от Peter Almazov Ноябрь 29, 2018, 07:11:05 am »
Хотелось бы зафиксировать одно наблюдение про цикл Дейкстры.
Оно, конечно, абсолютно очевидное, часто всплывает в примерах, но я не припомню, чтобы кто-то его четко сформулировал.
А именно: цикл Дейкстры всегда можно тупо преобразовать в обычный цикл без exit-ов и break-ов.
Нужно собрать в заголовке все предохранители.

do
  P1 → S1,
  P2 → S2,
   …
  Pn → Sn
od

=>

while (P1 or P2 ... or Pn) do
  if P1 then
    S1;
  else if P2 then
    S2
    ...
  else if Pn then
    Sn
  end if
end while

Неэффективно, да.
Но полезно для рассуждений.



2
Общий раздел / Re: BlackBox без MDI
« Последний ответ от Ivan Denisov Октябрь 15, 2018, 03:56:43 am »
Переделал для 1.7
3
Общий раздел / qsort как так отсортировать
« Последний ответ от Jordan Сентябрь 18, 2018, 03:03:35 pm »
Приветствую!

Код

typedef struct critter
{
  int number;
  int value;
  char * name;
} critter;

int comp(const void* a, const void* b)
{
        const critter* k = (const critter*)a;
        const critter* m = (const critter*)b;
        int s = ((k -> number) - (m -> number));

        return s;
}

  critter mas[5];
 
  mas[0].number = 5;
  mas[1].number = 4;
  mas[2].number = 3;
  mas[3].number = 2;
  mas[4].number = 1;
 
 
  qsort(mas, 5, sizeof(critter), comp);
 
  for (size_t i = 0; i < 5; i++)
  {
    printf("%d\n", mas.number);
  }


Как перестроить функцию сравнения так, что бы в аргументы можно было передать не только number, но и value

int comp(const void* a, const void* b)
{
        const critter* k = (const critter*)a;
        const critter* m = (const critter*)b;
        int s = ((k -> number) - (m -> number)); // в аргументы функции можно было передать value не изменяя функцию

        return s;
}

Так не надо.
int comp(const void* a, const void* b)
{
        const critter* k = (const critter*)a;
        const critter* m = (const critter*)b;
        int s = ((k -> value) - (m -> value));

        return s;
}

Генерируется код

typedef struct critter_vector
{
  size_t total;
  size_t pos;
  critter * data;
} critter_vector;

int critter_vector_compare_int(const void *a, const void *b)
{
  return *(int *)a - *(int *)b;
}

void critter_vector_sort_int(critter_vector * src)
{
 qsort(src->data, critter_vector_size(src), sizeof(critter), critter_vector_compare_int); //как передать не только number но и value
}

Так как поля critter будут разные. Не понимаю как всё это сделать.
4
Общий раздел / Re: деструкторы С++ и аналог в си
« Последний ответ от Jordan Сентябрь 18, 2018, 06:58:59 am »
Понял. Без умного указателя деструктор объектов в векторе не вызывается.

Сначала нужно удалить вручную память по указателям, после чего при выходе из области видимости вектора, он уничтожается.

Получается, что к примеру указатель на объект может быть и в другом векторе или контейнере и при уничтожении вектора, указатель в другой контейнере будет не валиден.

Тогда, нужно в моем случае сделать два контейнера, с возможностью вызова деструктора и без.

unique_ptr_vector деструкор вызовется автоматически при уничтожении вектора, вручную контролировать уникальность, так как в си такую проверку не сделать

ptr_vector массив указателей при уничтожении вектора, проходить в ручную по массиву и вызывать деструктор
5
Общий раздел / Re: деструкторы С++ и аналог в си
« Последний ответ от valexey_u Сентябрь 18, 2018, 12:57:02 am »
Для этого сделаны умные указатели (то есть в деструкторе уже указателя вызывается деструктор объекта на который он указывает): https://en.cppreference.com/w/cpp/memory/shared_ptr
https://en.cppreference.com/w/cpp/memory/unique_ptr

Умный указатель это не что-то вшитое в язык, это обычный класс, такой в плюсах можно сделать самостоятельно.
6
Общий раздел / деструкторы С++ и аналог в си
« Последний ответ от Jordan Сентябрь 16, 2018, 07:38:37 pm »
Приветствую!

Написал прогу которая генерирует типизированные контейнеры для си. По ходу написания всплыл вопрос о деструкторах.

Код на основе которого генерируется контейнер

typedef struct NAME_vector
{
  size_t total;
  size_t pos;
  TYPE * data;
} NAME_vector;

inline NAME_vector * NAME_vector_new(size_t count)
{
  NAME_vector * p = (NAME_vector*)calloc(1, sizeof(NAME_vector));
 
  p->total = count;
  p->pos   = 0;
  p->data  = (TYPE*)calloc(p->total, sizeof(TYPE));
 
  return p;
}

inline void NAME_vector_clear(NAME_vector * src)
{
  src->pos = 0;
}

inline size_t NAME_vector_size(NAME_vector * src)
{
  return src->pos;
}

inline size_t NAME_vector_capacity(NAME_vector * src)
{
  return src->total;
}

inline TYPE * NAME_vector_get(NAME_vector * src, size_t idx)
{
  assert(idx <= NAME_vector_size(src));

  return &src->data[idx];
}

inline void NAME_vector_free(NAME_vector * src)
{
  for (size_t i = 0; i < NAME_vector_size(src); i++)
  {
    TYPE * j = NAME_vector_get(src, i);
    NAME_destroy(j);
  }
 
  free(src->data);
  free(src);
}

/*
inline void NAME_vector_free(NAME_vector * src)
{
  free(src->data);
  free(src);
}
*/

inline void NAME_vector_set(NAME_vector * src, size_t idx, TYPE val)
{
  memcpy(&src->data[idx], &val, sizeof(TYPE));
}

inline void NAME_vector_resize(NAME_vector * src, size_t count)
{
  if (count > src->total)
  {
    src->total = count;
    src->data  = (TYPE*)realloc(src->data, src->total * sizeof(TYPE));
  }
}

inline void NAME_vector_push_back(NAME_vector * src, const TYPE val)
{
  if (src->pos + 1 > src->total)
  {
    src->total = src->total * 2;
    src->data  = (TYPE*)realloc(src->data, src->total * sizeof(TYPE));
  }

  memcpy(&src->data[src->pos], &val, sizeof(TYPE));
  src->pos++;
}


Код деструктора для вектора

inline void critter_ptr_vector_free(critter_ptr_vector * src)
{
  for (size_t i = 0; i < critter_ptr_vector_size(src); i++)
  {
    critter * j = critter_ptr_vector_get(src, i);
    critter_destroy(j);
  }
 
  free(src->data);
  free(src);
}

Сам код данного объекта

#define critter_max (32)

typedef struct
{
  char * name;
  uint16_t base [critter_max];
  uint16_t bonus[critter_max];
} critter;

void critter_init(critter * src, const char * name)
{
  src->name = strdup(name);

  for (size_t i = 0; i < critter_max; i++)
  {
    src->base = 5;
  }
 
  for (size_t j = 0; j < critter_max; j++)
  {
    src->bonus[j] = 7;
  }
}

void critter_destroy(critter * src)
{
  free(src->name);
}

Вроде все понятно. При уничтожении ветора все объекты будут корректно уничтожены, главное реализовать деструктор для хранимого объекта.

Но если хранить не объекты а указатели на объекты.

typedef struct NAME_ptr_vector
{
  size_t total;
  size_t pos;
  TYPE ** data;
} NAME_ptr_vector;

inline NAME_ptr_vector * NAME_ptr_vector_new(size_t count)
{
  NAME_ptr_vector * p = (NAME_ptr_vector*)calloc(1, sizeof(NAME_ptr_vector));
 
  p->total = count;
  p->pos   = 0;
  p->data  = (TYPE**)calloc(p->total, sizeof(TYPE*));
 
  return p;
}

inline void NAME_ptr_vector_clear(NAME_ptr_vector * src)
{
  src->pos = 0;
}

inline size_t NAME_ptr_vector_size(NAME_ptr_vector * src)
{
  return src->pos;
}

inline size_t NAME_ptr_vector_capacity(NAME_ptr_vector * src)
{
  return src->total;
}

inline TYPE * NAME_ptr_vector_get(NAME_ptr_vector * src, size_t idx)
{
  assert(idx <= NAME_ptr_vector_size(src));

  return src->data[idx];
}

inline void NAME_ptr_vector_free(NAME_ptr_vector * src)
{
  for (size_t i = 0; i < NAME_ptr_vector_size(src); i++)
  {
    TYPE * j = NAME_ptr_vector_get(src, i);
    NAME_destroy(j);
  }
 
  free(src->data);
  free(src);
}

/*
inline void NAME_ptr_vector_free(NAME_ptr_vector * src)
{
  free(src->data);
  free(src);
}
*/

inline void NAME_ptr_vector_set(NAME_ptr_vector * src, size_t idx, TYPE * val)
{
  src->data[idx] = val;
}

inline void NAME_ptr_vector_resize(NAME_ptr_vector * src, size_t count)
{
  if (count > src->total)
  {
    src->total = count;
    src->data  = (TYPE**)realloc(src->data, src->total * sizeof(TYPE*));
  }
}

inline void NAME_ptr_vector_push_back(NAME_ptr_vector * src, TYPE * val)
{
  if (src->pos + 1 > src->total)
  {
    src->total = src->total * 2;
    src->data  = (TYPE**)realloc(src->data, src->total * sizeof(TYPE*));
  }

  src->data[src->pos] = val;
  src->pos++;
}

Генерируется вектор указателей. Код почти аналогичен.

Вопрос в том, что в С++ деструктор для указателей объектов которые находятся в векторе не вызывается автоматически. Для чего это сделано?
Стоит ли в моей реализации поступить так же?
7
Общий раздел / Re: Опережающее определение struct в си
« Последний ответ от kkkk Сентябрь 15, 2018, 05:56:18 pm »
Имя тэга после ключевого слов struct должно отличаться от имени, задаваемого "переменной"-типом через typedef, так как в С++ это способы определения синонимичны, а в С - нет. Поэтому в Си компилируется без проблем, а в С++ это повторное задание идентификатора в той же области видимости
8
Общий раздел / Re: Опережающее определение struct в си
« Последний ответ от Jordan Сентябрь 15, 2018, 05:27:57 pm »
За то теперь ругается компилятор с++, си компилирует.
9
Общий раздел / Re: Опережающее определение struct в си
« Последний ответ от Jordan Сентябрь 15, 2018, 05:24:39 pm »
Разобрался нужно объявить struct widget_vector * childs;
10
Общий раздел / Re: Опережающее определение struct в си
« Последний ответ от Jordan Сентябрь 15, 2018, 04:03:14 pm »
Смысл в том, что бы не меняя язык, внешней программой генерировать типобезопасные контейнеры для си. Вообще подходит для любого языка. Потому и в обероне можно сделать типобезопасный stl, не меняя язык. Не так удобно, но работает.
Страницы: [1] 2 3 ... 10