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.

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.