Я пытаюсь преобразовать вектор 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++;
}
я знаю, что c не имеет этих функций, поэтому я делаю это в первую очередь в связанном списке
Вы хотите реализовать эквивалент std::vector<T>::push_back() (общий) или std::vector<SomeSpecificType>::push_back(), где вы знаете тип хранимого времени?
основной вопрос касается типа данных, более безопасный способ, если иметь выделенный vector_xx для каждого необходимого типа. Обратите внимание, что вы можете использовать макрос для определения соответствующего vector_xx без необходимости каждый раз делать это вручную.
Я пытаюсь реализовать SomeSpecificType, например, я хочу, чтобы тип данных был символом @BoR
C не имеет понятия о функциях-членах, поэтому вы не можете делать vectorName.push_back(string) в C - по крайней мере, если вы хотите, чтобы он вел себя удаленно, как эквивалент C++. Да, структура C может содержать указатели на функции, но ее использование полностью отличается от функций-членов C++.
@Peter в конечных функциях-членах преобразуются в функции, где первый параметр является указателем на тип, у них даже есть собственное соглашение о вызовах __thiscall. C-функции-«члены» будут семантически разными, но функционально эквивалентными.
@vandench - вы имеете в виду конкретную работу одного компилятора (или семейства компиляторов). В стандартном C нет семантического или функционального эквивалента. Если вы собираетесь преобразовывать код C++ в C, используя расширения, специфичные для одного компилятора, вам лучше просто использовать компилятор C++.





Пример :
#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;
}
std::vector в значительной степени зависит от возможностей C++, таких как создание копий (и, конечно же, шаблонов), которых в C просто нет. Не думаю, что это взлетит.