#ifndef vECTOR_h
#define vECTOR_h
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
/* My iterator is an int but thanks to this typedef I could change it easily */
typedef int iterator;
#define iterator_begin 0
#define iterator_end -1
//typedef is for vector_type and in the meanwhile struct vector_struct is defined
typedef struct vector_struct {
size_t e_sz; //size of a single element in e_array in bytes, size_t is always unigned and machine/compiler bounded usually undsinged long
char e_type; //type of a single element in e_array used rarely since we go with void pointers
#define V_INT 1
#define V_DOUBLE 2
#define V_CHAR 3
#define V_FLOAT 4
unsigned no_e; //number of elements in e_array with a value , unsigned alone means unsigned int
unsigned cur_cap; //max capacity of e_array at that moment
void* e_array; //real data
}* vector_type;
#define vector_size(v) ((v)->no_e)
#define vector_capacity(v) ((v)->cur_cap)
#define vector_int_at(v,i) (*((int*)v_at(v,i)))
#define vector_double_at(v,i) (*((double*)v_at(v,i)))
#define vector_char_at(v,i) (*((char*)v_at(v,i)))
#define vector_string(v) ((char*)v_at(v,0))
#define vector_float_at(v,i) (*((float*)v_at(v,i)))
//not necessary defines
//Allocate space for a vector struct and initialize some elements
vector_type v_create_empty(char type){
vector_type my_v = (vector_type)check_a(malloc(sizeof(struct vector_struct)));
//since it's used only here we could drop type and receive size direclty where in vector.h we #define V_INT_S sizeof(int)
//on the other hand a better typed implementation would do a large use of e_type, less void pointer and more typed casts
my_v->e_sz = (type == V_INT ? sizeof(int) : type == V_DOUBLE ? sizeof(double) : type == V_FLOAT ? sizeof(float) : 1); //1 for default is char then sizeof(char)
my_v->e_type = type;
my_v->no_e = my_v->cur_cap = 0;
my_v->e_array = NULL;
return my_v;
}
void* v_at(vector_type v, iterator i){
if ( v == NULL )
fail("v_at() Error: no such vector");
if ( i == iterator_end )
i = v->no_e -1;
if ( i < 0 || i >= v->no_e )
fail("v_at() Error: no such element in this vector");
return (void*)((char*)v->e_array + (i * v->e_sz)) ; //i sum char to char
//in order to get the specified position of variable type casting to void* for the return value
//
//typed alternative solution
//
// switch(v->type)
// {
// case V_INT:
// return ((void*)((int*)v->e_array) + i) ;
// break;
// case V_DOUBLE:
// return ((void*)((double*)v->e_array) + i) ;
// break;
// case V_FLOAT:
// return ((void*)((float*)v->e_array) + i) ;
// break;
// default:
// return ((void*)((char*)v->e_array) + i) ;
// break;
// }
}
//Function to push some elements back to the first v->e_array void pointer and so on
void v_push_back(vector_type v, void* new_val){
if ( v->no_e >= v->cur_cap ) {
/*** reallocate a larger array ***/
v->cur_cap += (v->cur_cap)? v->cur_cap : 2;
//add 2 elements if v->cur_cap is 0
//if that's first call malloc will be used
void *ptr = realloc(v->e_array,v->cur_cap * v->e_sz);
if (ptr == NULL)
{
ptr = check_a(malloc(v->cur_cap * v->e_sz));
memcpy(ptr, v->e_array ,v->no_e * v->e_sz);
free(v->e_array);
v->e_array = ptr;
}
v->e_array = check_a(realloc(v->e_array,v->cur_cap * v->e_sz));
//v->cur_cap * v->e_sz is never 0
}
/*** copy new_val in the array at index v->no_e ***/
v->e_array = check_a(memcpy((void*)((char*)v->e_array + (v->no_e * v->e_sz)) , new_val, v->e_sz));
(v->no_e)++;
}
// v_push_back FUNCTION CALLED LIKE THIS from main in another c file:
// the purpose is to link all characters in an array of characters
c1 = 'c'; v_push_back(vc1,(void*)&c1);
c1 = 'i'; v_push_back(vc1,(void*)&c1);
c1 = 'a'; v_push_back(vc1,(void*)&c1);
c1 = 'o'; v_push_back(vc1,(void*)&c1);
c1 = 0; v_push_back(vc1,(void*)&c1);
printf("Vector vc1 now contains %d characters (capacity=%d): %s\n",
vector_size(vc1)/**((v)->no_e)**/,vector_capacity(vc1)/** ((v)->cur_cap)**/,vector_string(vc1))/** ((char*)v_at(v,0))**/; // ==>ERROR DOESN 'T PRINT THE %s of (char*)v_at(v,0)
我不能打印通过推回数组列表的元素创建的字符串的值,在调试期间没有分段错误,你有时会读取函数check_a(指针*)它只包含一个控制一个NULL指针,每次在malloc,realloc ...命令
之后调用许多代码丢失但是这里是有缺陷的部分 这是一个应该实现float,int等数组的程序;因此,为了保持通用性,有时需要转换为void *,有时会转换为char *以逐字节移动。
答案 0 :(得分:0)
v_push_back实现出错:
v->e_array = check_a(memcpy((void*)((char*)v->e_array + (v->no_e * v->e_sz)) ,new_val, v->e_sz)); //pointer has not to be saved
check_a(memcpy((void*)((char*)v->e_array + (v->no_e * v->e_sz)) ,new_val, v->e_sz));
因为memcpy返回一个指针,在这种情况下,返回到数组的最后一个元素,所以我们将失去对所有先前内存的访问权