2016-08-01 6 views
0

Ich möchte meinen generischen Vektor verwenden, um die Daten aus einer Zeile in der CSV-Datei zu halten. Aber ich treffe ein Problem. Meine Eingabe ist:Warum verketten sich die Ausgabezeichenfolgen auf seltsame Weise?

MonsterID, Namens-, Hitpoints, Angriff, Verteidigung, AttackTimes, Gold, Exp, Sonder

Der Ausgang werden

Field 0 would be MonsterIName 
Field 1 would be Name 
Field 2 would be HitpointAttack 
Field 3 would be Attack 
Field 4 would be Defence 
Field 5 would be AttackTiGold 
Field 6 would be Gold 
Field 7 would be Exp 
Field 8 would be Special 

Hier sind die Teile des Codes relevant für dieses Problem:

Definition des Vector Typ:

typedef void (*VectorFreeFunction)(void *element); 

typedef struct Vector { 
    void *elements; // An array of elements 
    int capacity;  // The allocated size of the array 
    int size;   // The number of elements in use 
    size_t elemSize; // Size of the data type of the element. 
    VectorFreeFunction freeFunc; 
} Vector; 

csv.c

... 
Vector *getfields(char *line) { 
    int i = 0; 
    const char *token; 

    Vector *fields = vectorAlloc(sizeof(char*), NULL); 

    for (token = strtok(line, ","); 
     token && *token; 
     token = strtok(NULL, ",\n"), i++) 
    { 
     vectorPush(fields, (const void*)token); 
    } 

    for (int i = 0; i != fields->size; i++) { 
     printf("Field %d would be %s\n", i, (const char*)vectorAt(fields, i)); 
    } 

    return fields; 
} 

vector.c

Vector *vectorAlloc(size_t elemSize, VectorFreeFunction freeFunc) { 
    Vector *vector = malloc(sizeof(Vector)); 
    if (vector == NULL) { 
     fatalError("Cannot allocate vector"); 
    } 

    vector->capacity = DEFAULT_CAPACITY; 
    vector->size = 0; 
    vector->elemSize = elemSize; 

    vector->elements = malloc(elemSize * vector->capacity); 
    if (vector->elements == NULL) { 
     fatalError("Cannot allocate elements array of the vector"); 
    } 

    vector->freeFunc = freeFunc; 
    return vector; 
} 

void *vectorAt(Vector *vector, int position) { 
    assert(position < vector->size && position >= 0); 
    return ((char*)vector->elements + (position * vector->elemSize)); 
} 

void vectorPush(Vector *vector, const void *element) { 

    if (vector->size == vector->capacity) { 
     _vectorDoubleCapacity(vector); 
    } 

    void *destAddr = (char*)vector->elements + vector->size * vector->elemSize; 
    memcpy(destAddr, element, vector->elemSize); // add to end of vector 

    vector->size++; 
} 

void _vectorDoubleCapacity(Vector *vector) { 
    vector->capacity *= 2; 

    vector->elements = realloc(vector->elements, vector->elemSize * vector->capacity); 
    if (vector->elements == NULL) { 
     fatalError("Resizing the capacity of vector fails"); 
    } 
} 
+2

Sie etwas dagegen die Schaffung eines [___MCVE___] (http://stackoverflow.com/help/mcve)? –

+1

Dies ist zu minimal, z.B. 'Vector' Definition fehlt. –

+0

Ich verwende elemSize nicht für zwei verschiedene Dinge. Aber Ihr Kommentar dazu, dass ich Probleme mit Strings größer als 8 Bytes habe, ist aufschlussreich. Ich sollte das jetzt überprüfen. –

Antwort

1

Die Elemente, die Sie auf die Vector schieben sind Zeiger in das Array von der zu getfieldsline Argument hingewiesen. Es ist schwierig, die Lebensdauer der Vector Elemente auf diese Weise zu überwachen, stattdessen sollten Sie Kopien der Token mit strdup() zuweisen und free als VectorFreeFunction übergeben, wenn Sie die Vector erstellen.

Futhermore, vectorAt einen Zeiger auf das Vektor-Element zurückgibt, die selbst ein char *, so, wie Sie es verwenden, um den Inhalt des Vector zu drucken ist falsch: Sie können es als (char **) und dereferenzieren werfen sollte. Hier

ist eine korrigierte Version:

Vector *getfields(char *line) { 
    int i = 0; 
    const char *token; 

    Vector *fields = vectorAlloc(sizeof(char*), free); 

    for (token = strtok(line, ","); 
     token && *token; 
     token = strtok(NULL, ",\n"), i++) { 
     vectorPush(fields, strdup(token)); 
    } 

    for (int i = 0; i < fields->size; i++) { 
     printf("Field %d would be %s\n", i, *(char **)vectorAt(fields, i)); 
    } 

    return fields; 
}