Hi everyone,

I've been trying to code up a generic vector implementation in C, and the compiler has not been kind to me...

Here is the struct I have defined in a file "vector.h."

typedef struct
 72 {
 73     int elemSize;
 74     int logLength;
 75     int allocLength;
 76     int delta;
 77     void* elems;
 78     VectorFreeFunction freefn;
 79 }vector;

VectorFreeFunction is typedef-ed in vector.h

typedef void (*VectorFreeFunction)(void *elemAddr);

Now in "vector.c" the implementation file for the Vector, I have the following method.

void VectorNew(vector* v, int elemSize, VectorFreeFunction freeFn, int initialAllocation)
{
    assert(elemSize > 0);
    assert(initialAllocation >= 0);
    v->elemSize = elemSize;
    if(initialAllocation == 0)
        initialAllocation = 10;
    v->allocLength = initialAllocation;
    v->delta = initialAllocation;
    v->logLength = 0;
    v->freefn = freeFn;
    v->elems = malloc(v->allocLength * elemSize);
}

For some reason, gcc is giving me an error on the first line of this method telling me

expected ‘)’ before ‘*’ token

everytime I try to define a parameter as "vector* v".

What is it that I am doing wrong?

Does vector.h include vector.h ?
Check for a missing ; either at the end of the .h file, or earlier on in the .c file.

vector.c includes vector.h.. I don't see any missing ';' in the files, and the error I'm receiving:

error: expected ‘)’ before ‘*’ token

shows up everytime I define the parameter as vector *v

Does vector.h include vector.h ?
Check for a missing ; either at the end of the .h file, or earlier on in the .c file.

Unless you can post an actual bit of code we can copy/paste into a compiler, then I'm afraid there isn't much to say.

The problem isn't in the bit you posted, it lies elsewhere.

Here..

vector.c

#include "vector.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

void VectorNew(vector* v, int elemSize, VectorFreeFunction freeFn, int initialAllocation)
{
    assert(elemSize > 0);
    assert(initialAllocation >= 0);
    v->elemSize = elemSize;
    if(initialAllocation == 0)
        initialAllocation = 10;
    v->allocLength = initialAllocation;
    v->delta = initialAllocation;
    v->logLength = 0;
    v->freefn = freeFn;
    v->elems = malloc(v->allocLength * elemSize);
}

void VectorDispose(vector* v)
{
    char* ptr = (char*) v->elems;
    for(int i=0; i< v->logLength; i++, ptr += v->elemSize)
        v->freefn((void*) ptr);
    free(v->elems);
}

int VectorLength(const vector* v)
{
    return v->logLength; 
}

void *VectorNth(const vector* v, int position)
{
    assert(position < v->logLength && position >= 0);
    char* ptr = (char *)v ->elems;
    return ptr + v->elemSize * position;
}

void VectorReplace(vector* v, const void *elemAddr, int position)
{
    assert(position < v->logLength && position >=0);
    char* ptr = (char *)v ->elems + v->elemSize * position;
    v->freefn(ptr); //free the old element
    memcpy(ptr,elemAddr,v->elemSize);//copy the new element
}

void VectorInsert(vector* v, const void *elemAddr, int position)
{
    assert(position < v->logLength && position >=0);

    if(v->logLength == v-> allocLength)//realloc needed
    {
        v->allocLength += v->delta;
        v->elems = realloc(v->elems,v->allocLength * v->elemSize);
        assert(v->elems); //!= NULL implied. 
    }
    int size = v->logLength - position;
    char buffer[size];
    char * nthptr = VectorNth(v,position);
    memcpy(buffer,nthptr,size * v->elemSize); //copy to buffer.
    memcpy(nthptr,elemAddr,v->elemSize); //insert the thing.
    memcpy(nthptr + v->elemSize, buffer, size * v->elemSize); //copy after thing
    v->logLength++;
}

void VectorAppend(vector* v, const void *elemAddr)
{
    void* destAddr;
    if(v->logLength == v-> allocLength)//realloc needed
    {
        v->allocLength += v->delta;
        v->elems = realloc(v->elems,v->allocLength * v->elemSize);
        assert(v->elems); //!= NULL implied. 
    }
    destAddr = (char*) v->elems + v->logLength * v->elemSize;
    memcpy(destAddr,elemAddr,v->elemSize);
    v->logLength++;
}

void VectorDelete(vector* v, int position)
{
    assert(position < v->logLength && position >=0);

    int size = v->logLength - position -1; //When you delete you copy one less thing
    char * nthptr = VectorNth(v,position);
    memmove(nthptr,nthptr+v->elemSize,size * v->elemSize); //copy to buffer.
    v->logLength--;
}

void VectorSort(vector* v, VectorCompareFunction compare)
{
    assert(compare);
    qsort(v->elems,v->logLength,v->elemSize,compare);    
}

void VectorMap(vector* v, VectorMapFunction mapFn, void *auxData)
{
    char* ptr = v ->elems;
    assert(mapFn);
    for(int i=0; i < v->logLength; i++, ptr += v->elemSize)
    {
        mapFn(v,auxData);
    }
}

static const int kNotFound = -1;
int VectorSearch(const vector* v, const void *key, VectorCompareFunction searchFn, int startIndex, bool isSorted)
{
    assert(startIndex >= 0);
    void* nptr = VectorNth(v,startIndex);
    void* result;
    if(isSorted)
        result = bsearch(key,nptr,v->logLength - startIndex,v->elemSize,searchFn); 
    else
    {
        for(int i=0; i<v->logLength - startIndex; i++)
            if(searchFn(nptr,key) == 0)
                return startIndex + i;
        return kNotFound;
    } 
    if(result == NULL)
        return kNotFound;
    return ((char*)result - (char*)v->elems)/v->elemSize;
}
/** 
 * File: vector.h
 * ---------------
 * Defines the interface for the vector.
 *
 * The vector allows the client to store any number of elements of any desired
 * primitive type and is appropriate for a wide variety of storage problems.  It 
 * supports efficient element access and appending/inserting/deleting elements
 * as well as optional sorting and searching.  In all cases, the vector imposes 
 * no upper bound on the number of elements and deals with all its own memory 
 * management. The client specifies the size (in bytes) of the elements that 
 * will be stored in the vector when it is created.  Thereafter the client and 
 * the vector can refer to elements via (void *) ptrs.
 */

#ifndef _vector_
#define _vector_

#include "bool.h"
#include "vector.c"

/**
 * Type: VectorCompareFunction
 * ---------------------------
 * VectorCompareFunction is a pointer to a client-supplied function which the
 * vector uses to sort or search for elements.  The comparator takes two 
 * (const void *) pointers (these will point to elements) and returns an int.
 * The comparator should indicate the ordering of the two elements
 * using the same convention as the strcmp library function:
 * 
 *   If elemAddr1 is less than elemAddr2, return a negative number.
 *   If elemAddr1 is greater than elemAddr2, return a positive number.
 *   If the two elements are equal, return 0.
 */

typedef int (*VectorCompareFunction)(const void *elemAddr1, const void *elemAddr2);

/** 
 * Type: VectorMapFunction
 * -----------------------
 * VectorMapFunction defines the space of functions that can be used to map over
 * the elements in a vector.  A map function is called with a pointer to
 * the element and a client data pointer passed in from the original
 * caller.
 */

typedef void (*VectorMapFunction)(void *elemAddr, void *auxData);

/** 
 * Type: VectorFreeFunction
 * ---------------------------------
 * VectorFreeFunction defines the space of functions that can be used as the
 * clean-up function for each element as it is deleted from the vector
 * or when the entire vector is destroyed.  The cleanup function is 
 * called with a pointer to an element about to be deleted.
 */

typedef void (*VectorFreeFunction)(void *elemAddr);

/**
 * Type: vector
 * ------------
 * Defines the concrete representation of
 * the vector.  Even though everything is
 * exposed, the client should respect the 
 * the privacy of the representation and initialize,
 * dispose of, and otherwise interact with a
 * vector using those functions defined in this file.
 */

typedef struct 
{
    int elemSize;
    int logLength;
    int allocLength;
    int delta;
    void* elems;
    VectorFreeFunction freefn;
}vector;

/** 
 * Function: VectorNew
 * Usage: vector myFriends;
 *        VectorNew(&myFriends, sizeof(char *), StringFree, 10);
 * -------------------
 * Constructs a raw or previously destroyed vector to be the
 * empty vector.
 * 
 * The elemSize parameter specifies the number of bytes that a single 
 * element of the vector should take up.  For example, if you want to store 
 * elements of type char *, you would pass sizeof(char *) as this parameter.
 * An assert is raised if the size is not greater than zero.
 *
 * The ArrayFreeFunction is the function that will be called on an element that
 * is about to be deleted (using VectorDelete) or on each element in the
 * vector when the entire vector is being freed (using VectorDispose).  This function
 * is your chance to do any deallocation/cleanup required for the element
 * (such as freeing/deleting any pointers contained in the element). The client can pass 
 * NULL for the ArrayFreeFunction if the elements don't require any special handling.
 *
 * The initialAllocation parameter specifies the initial allocated length 
 * of the vector, as well as the dynamic reallocation increment for those times when the 
 * vector needs to grow.  Rather than growing the vector one element at a time as 
 * elements are added (inefficient), you will grow the vector 
 * in chunks of initialAllocation size.  The allocated length is the number
 * of elements for which space has been allocated: the logical length 
 * is the number of those slots currently being used.
 * 
 * A new vector pre-allocates space for initialAllocation elements, but the
 * logical length is zero.  As elements are added, those allocated slots fill
 * up, and when the initial allocation is all used, grow the vector by another 
 * initialAllocation elements.  You will continue growing the vector in chunks
 * like this as needed.  Thus the allocated length will always be a multiple
 * of initialAllocation.  Don't worry about using realloc to shrink the vector's 
 * allocation if a bunch of elements get deleted.  It turns out that 
 * many implementations of realloc don't even pay attention to such a request, 
 * so there is little point in asking.  Just leave the vector over-allocated and no
 * one will care.
 *
 * The initialAllocation is the client's opportunity to tune the resizing
 * behavior for his/her particular needs.  Clients who expect their vectors to
 * become large should probably choose a large initial allocation size, whereas
 * clients who expect the vector to be relatively small should choose a smaller
 * initialAllocation size.  You want to minimize the number of reallocations, but
 * you don't want to pre-allocate all that much memory if you don't expect to use very
 * much of it.  If the client passes 0 for initialAllocation, the implementation
 * will use the default value of its own choosing.  As assert is raised is 
 * the initialAllocation value is less than 0.
 */

void VectorNew(vector *v, int elemSize, VectorFreeFunction freefn, int initialAllocation);

/**
 * Function: VectorDispose
 *           VectorDispose(&studentsDroppingTheCourse);
 * -----------------------
 * Frees up all the memory of the specified vector and its elements.  It does *not* 
 * automatically free memory owned by pointers embedded in the elements. 
 * This would require knowledge of the structure of the elements, which the 
 * vector does not have.  However, it *will* iterate over the elements calling
 * the VectorFreeFunction previously supplied to VectorNew.
 */

void VectorDispose(vector *v);

/**
 * Function: VectorLength
 * ----------------------
 * Returns the logical length of the vector, i.e. the number of elements
 * currently in the vector.  Must run in constant time.
 */

int VectorLength(const vector *v);
	   
/**
 * Method: VectorNth
 * -----------------
 * Returns a pointer to the element numbered position in the vector.  
 * Numbering begins with 0.  An assert is raised if n is less than 0 or greater 
 * than the logical length minus 1.  Note this function returns a pointer into 
 * the vector's storage, so the pointer should be used with care.
 * This method must operate in constant time.
 *
 * We could have written the vector without this sort of access, but it
 * is useful and efficient to offer it, although the client needs to be 
 * careful when using it.  In particular, a pointer returned by VectorNth 
 * becomes invalid after any calls which involve insertion into, deletion from or 
 * sorting of the vector, as all of these may rearrange the elements to some extent.
 */ 

void *VectorNth(const vector *v, int position);
					  
/**
 * Function: VectorInsert
 * ----------------------
 * Inserts a new element into the specified vector, placing it at the specified position.
 * An assert is raised if n is less than 0 or greater than the logical length.
 * The vector elements after the supplied position will be shifted over to make room. 
 * The element is passed by address: The new element's contents are copied from 
 * the memory pointed to by elemAddr.  This method runs in linear time.
 */

void VectorInsert(vector *v, const void *elemAddr, int position);

/**
 * Function: VectorAppend
 * ----------------------
 * Appends a new element to the end of the specified vector.  The element is 
 * passed by address, and the element contents are copied from the memory pointed 
 * to by elemAddr.  Note that right after this call, the new element will be 
 * the last in the vector; i.e. its element number will be the logical length 
 * minus 1.  This method must run in constant time (neglecting the memory reallocation 
 * time which may be required occasionally).
 */

void VectorAppend(vector *v, const void *elemAddr);
  
/**
 * Function: VectorReplace
 * -----------------------
 * Overwrites the element at the specified position with a new value.  Before 
 * being overwritten, the VectorFreeFunction that was supplied to VectorNew is levied
 * against the old element.  Then that position in the vector will get a new value by
 * copying the new element's contents from the memory pointed to by elemAddr.
 * An assert is raised if n is less than 0 or greater than the logical length 
 * minus one.  None of the other elements are affected or rearranged by this
 * operation, and the size of the vector remains constant. This method must
 * operate in constant time.
 */

void VectorReplace(vector *v, const void *elemAddr, int position);

/**
 * Function: VectorDelete
 * ----------------------
 * Deletes the element at the specified position from the vector. Before the 
 * element is removed,  the ArrayFreeFunction that was supplied to VectorNew
 * will be called on the element.
 *
 * An assert is raised if position is less than 0 or greater than the logical length 
 * minus one.  All the elements after the specified position will be shifted over to fill 
 * the gap.  This method runs in linear time.  It does not shrink the 
 * allocated size of the vector when an element is deleted; the vector just 
 * stays over-allocated.
 */

void VectorDelete(vector *v, int position);
  
/* 
 * Function: VectorSearch
 * ----------------------
 * Searches the specified vector for an element whose contents match
 * the element passed as the key.  Uses the comparator argument to test
 * for equality.  The startIndex parameter controls where the search
 * starts.  If the client desires to search the entire vector,
 * they should pass 0 as the startIndex.  The method will search from
 * there to the end of the vector.  The isSorted parameter allows the client 
 * to specify that the vector is already in sorted order, in which case VectorSearch
 * uses a faster binary search.  If isSorted is false, a simple linear search is 
 * used.  If a match is found, the position of the matching element is returned;
 * else the function returns -1.  Calling this function does not 
 * re-arrange or change contents of the vector or modify the key in any way.
 * 
 * An assert is raised if startIndex is less than 0 or greater than
 * the logical length (although searching from logical length will never
 * find anything, allowing this case means you can search an entirely empty
 * vector from 0 without getting an assert).  An assert is raised if the
 * comparator or the key is NULL.
 */  

int VectorSearch(const vector *v, const void *key, VectorCompareFunction searchfn, int startIndex, bool isSorted);

/**
 * Function: VectorSort
 * --------------------
 * Sorts the vector into ascending order according to the supplied
 * comparator.  The numbering of the elements will change to reflect the 
 * new ordering.  An assert is raised if the comparator is NULL.
 */

void VectorSort(vector *v, VectorCompareFunction comparefn);

/**
 * Method: VectorMap
 * -----------------
 * Iterates over the elements of the vector in order (from element 0 to
 * element n-1, inclusive) and calls the function mapfn on each element.  The function is 
 * called with the address of the vector element and the auxData pointer.  
 * The auxData value allows the client to pass extra state information to 
 * the client-supplied function, if necessary.  If no client data is required, 
 * this argument should be NULL.  An assert is raised if the mapfn function is NULL.
 */

void VectorMap(vector *v, VectorMapFunction mapfn, void *auxData);

#endif

Compiler errors I can't understand:
vector.c:7: error: expected ‘)’ before ‘*’ token
vector.c:21: error: expected ‘)’ before ‘*’ token
vector.c:29: warning: type defaults to ‘int’ in declaration of ‘vector’
vector.c:29: error: expected ‘;’, ‘,’ or ‘)’ before ‘*’ token
vector.c:34: warning: type defaults to ‘int’ in declaration of ‘vector’
vector.c:34: error: expected ‘;’, ‘,’ or ‘)’ before ‘*’ token
vector.c:41: error: expected ‘)’ before ‘*’ token
vector.c:49: error: expected ‘)’ before ‘*’ token
vector.c:68: error: expected ‘)’ before ‘*’ token
vector.c:82: error: expected ‘)’ before ‘*’ token
vector.c:92: error: expected ‘)’ before ‘*’ token
vector.c:98: error: expected ‘)’ before ‘*’ token
vector.c:109: warning: type defaults to ‘int’ in declaration of ‘vector’
vector.c:109: error: expected ‘;’, ‘,’ or ‘)’ before ‘*’ token
vector.c:108: error: redefinition of ‘kNotFound’
vector.c:108: note: previous definition of ‘kNotFound’ was here


Unless you can post an actual bit of code we can copy/paste into a compiler, then I'm afraid there isn't much to say.

The problem isn't in the bit you posted, it lies elsewhere.

So why does
vector.c include vector.h
AND
vector.h include vector.c

commented: Super helpful, as usual :) +6

Thank you so much!

So why does
vector.c include vector.h
AND
vector.h include vector.c

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.