Преобразование векторов C++ в C

Я пытаюсь преобразовать вектор vectorName; реализация cpp на C На самом деле я должен использовать некоторые из его функций, таких как vectorName.push_back(string) в C, но как мне это сделать, нет надлежащей реализации, и есть ли какой-либо способ, которым мы можем использовать библиотеки C++ и каким-то образом исправить его для кода C, это идея моя

typedef struct vector_ {
      void** data;
      int size;
      int count;
} vector;

void vector_add(vector*, void*);
void vector_add(vector *v, void *e)
{
    if (v->size == 0) {
        v->size = 10;
        v->data = malloc(sizeof(void*) * v->size);
        memset(v->data, '\0', sizeof(void*) * v->size);
    }

    if (v->size == v->count) {
        v->size *= 2;
        v->data = realloc(v->data, sizeof(void*) * v->size);
    }

    v->data[v->count] = e;
    v->count++;
}

std::vector в значительной степени зависит от возможностей C++, таких как создание копий (и, конечно же, шаблонов), которых в C просто нет. Не думаю, что это взлетит.

user2100815 23.02.2019 14:59

я знаю, что c не имеет этих функций, поэтому я делаю это в первую очередь в связанном списке

user8369850 23.02.2019 15:04

Вы хотите реализовать эквивалент std::vector<T>::push_back() (общий) или std::vector<SomeSpecificType>::push_back(), где вы знаете тип хранимого времени?

Bo R 23.02.2019 15:05

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

bruno 23.02.2019 15:06

Я пытаюсь реализовать SomeSpecificType, например, я хочу, чтобы тип данных был символом @BoR

user8369850 23.02.2019 15:19

C не имеет понятия о функциях-членах, поэтому вы не можете делать vectorName.push_back(string) в C - по крайней мере, если вы хотите, чтобы он вел себя удаленно, как эквивалент C++. Да, структура C может содержать указатели на функции, но ее использование полностью отличается от функций-членов C++.

Peter 23.02.2019 15:19

@Peter в конечных функциях-членах преобразуются в функции, где первый параметр является указателем на тип, у них даже есть собственное соглашение о вызовах __thiscall. C-функции-«члены» будут семантически разными, но функционально эквивалентными.

van dench 23.02.2019 15:22

@vandench - вы имеете в виду конкретную работу одного компилятора (или семейства компиляторов). В стандартном C нет семантического или функционального эквивалента. Если вы собираетесь преобразовывать код C++ в C, используя расширения, специфичные для одного компилятора, вам лучше просто использовать компилятор C++.

Peter 23.02.2019 15:29
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
8
469
2

Ответы 2

Пример :

#include <stdio.h>
#include <stdlib.h>

#define DEF_VECTOR(type) \
typedef struct vector_##type { \
  type * data; \
  size_t alloc_size; \
  size_t size; \
} vector_##type; \
\
void init_vector_##type(vector_##type * vector) \
{ \
  vector->data = NULL; \
  vector->alloc_size = vector->size = 0; \
} \
\
void clear_vector_##type(vector_##type * vector) \
{ \
  if (vector->data != NULL) {\
    free(vector->data); \
    init_vector_##type(vector);  \
  } \
} \
\
void push_back_vector_##type(vector_##type * vector, type value) \
{ \
  if (vector->size == vector->alloc_size) { \
    vector->alloc_size = (vector->alloc_size == 0) ? 16 : vector->alloc_size * 2; \
    vector->data = realloc(vector->data, vector->alloc_size * sizeof(type)); \
     \
    if (vector->data == NULL) { \
      /* do what you want */ \
    } \
  } \
  vector->data[vector->size++] = value; \
} \
\
type at_vector_##type(vector_##type * vector, size_t index) \
{ \
  if (index >= vector->size) { \
    /* do what you want */ \
  } \
  return vector->data[index]; \
}

DEF_VECTOR(int)

int main()
{
  vector_int v;

  init_vector_int(&v);
  push_back_vector_int(&v, 123);
  push_back_vector_int(&v, 456);
  printf("%d %d\n", at_vector_int(&v, 0), at_vector_int(&v, 1));
  printf("%d %d\n", v.data[0], v.data[1]);
  clear_vector_int(&v);
  return 0;
}

Компиляция и исполнение:

pi@raspberrypi:/tmp $ gcc -g -pedantic -Wextra v.c
pi@raspberrypi:/tmp $ ./a.out
123 456
123 456

Исполнение под валгринд

pi@raspberrypi:/tmp $ valgrind ./a.out
==11108== Memcheck, a memory error detector
==11108== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==11108== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==11108== Command: ./a.out
==11108== 
123 456
123 456
==11108== 
==11108== HEAP SUMMARY:
==11108==     in use at exit: 0 bytes in 0 blocks
==11108==   total heap usage: 2 allocs, 2 frees, 1,088 bytes allocated
==11108== 
==11108== All heap blocks were freed -- no leaks are possible
==11108== 
==11108== For counts of detected and suppressed errors, rerun with: -v
==11108== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)

Конечно, вы должны не забыть вызвать init_vector_xx и, если нужно, clear_vector_xx и использование макроса для определения всего не поможет, когда у вас есть ошибка при выполнении, потому что у вас нет номера строки и т. д.

Здесь я помещаю все в уникальный макрос, на самом деле лучше иметь макрос для определения структура и объявления функций, а другой - для определения функций, чтобы можно было поместить это в заголовки и исходники.

is there any way we can use c++ libraries and patch it to C code somehow

Не уверен, что на этот вопрос можно ответить. Конечно, вы можете почерпнуть некоторые идеи из их определений, потому что они хорошо реализованы, но вы также рискуете утонуть в сложности, которая вам не нужна в вашем переводе.

Однако, если вы можете остаться на C++, не переходите на C ;-)

Если вы хотите что-то похожее на std::vector<char>, то эквивалентное предложение решения push_back(char ch) может быть таким:

#include <stdlib.h>
#include <stdio.h>

typedef struct vectorOfChar vector;
struct vectorOfChar {
    char *start;
    char *finish;
    char *end_of_storage;
};

vector vector_construct(void) {
    vector v = {0};
    return v;
}

void vector_destruct(vector *const vec) {
    free(vec->start);
}

char *vector_data(vector *const vec) {
    return vec->start;
}

void vector_push_back(vector *const vec, char const ch) {
    if (vec->finish != vec->end_of_storage) {
        *vec->finish = ch;
        ++vec->finish;
    } else {
        int const size = vec->finish - vec->start;
        int capacity = vec->end_of_storage - vec->start;
        capacity++;
        capacity *= 3;
        capacity /= 2;
        char *const new_area = realloc(vec->start, capacity);
        if (new_area == NULL) {
            // define how to handle out-of-memory
            exit(EXIT_FAILURE);
        }
        vec->start = new_area;
        vec->finish = new_area + size;
        vec->end_of_storage = new_area + capacity;
        vector_push_back(vec, ch);
    }
}

int main() {
    vector v = vector_construct();

    for (char c = 'a'; c <= 'z'; c++) {
        vector_push_back(&v, c);
    }
    vector_push_back(&v, '\0');

    printf("%s\n", vector_data(&v));

    vector_destruct(&v);

    return EXIT_SUCCESS;
}

Другие вопросы по теме