2010-10-06 3 views
2

J'essaye d'écrire une base de données pour la classe dans laquelle je lis toutes les valeurs clés d'un fichier (formaté keyNULL BYTEvalueNULL BYTE etc). Je cherche à utiliser une liste liée pour cela, mais j'ai l'erreur que la structure n'a pas de valeur suivante. Aidez-moi, s'il vous plaît!Liste liée en C, pas d'erreur de membre

#include <stdio.h> 
#include <stdlib.h> 
#include <assert.h> 
#include <string.h> 
#include <stdbool.h> 

#include "sdbm.h" 

static FILE *db; 
static bool opened = false; 
static int err = 0, keyLen = 8; 

typedef struct { 
    char *name; 
    Key *next; 
} Key; 

static Key *head = NULL,*tail = NULL; 
/** 
* Create new database with given name. You still have 
* to sdbm_open() the database to access it. Return true 
* on success, false on failure. 
*/ 
bool sdbm_create(const char *name) { //Errors: 1) fopen failed 2) fclose failed on new db 
    db = fopen(name, "w"); 
    if (db == NULL) { 
    printf("Couldn't create file %s\n",name); 
    err = 1; 
    return false; 
    } 
    if (fclose(db) == EOF) { 
    printf("Couldn't close created file %s\n",name); 
    err = 2; 
    return false; 
    } 
    return true; 
} 
/** 
* Open existing database with given name. Return true on 
* success, false on failure. 
*/ 
bool sdbm_open(const char *name) { //Errors: 3) couldn't open database 
    db = fopen(name,"r+"); 
    if (db == NULL) { 
    err = 3; 
    printf("Couldn't open database file %s\n",name); 
    return false; 
    } 
    opened = true; 
    int c; 
    bool inKey = true; 
    int currKey[MAX_KEY_LENGTH]; 
    while ((c = getc(db)) != EOF) { 
    if (!inKey && c == '\0') { 
     inKey = true; 
    } 
    else if (inKey && c == '\0') { 
     if (tail != NULL) { 
     tail->next = malloc(sizeof(Key)); 
     tail = tail->next; 
     } 
     else { 
     tail = malloc(sizeof(Key)); 
     head = tail; 
     } 
     tail->next = NULL; 
     tail->name = currKey; 

    } 
    else if (inKey) { 
     currKey[keyLen] = c; 
     keyLen++; 
    } 
    } 
} 
/** 
* Synchronize all changes in database (if any) to disk. 
* Useful if implementation caches intermediate results 
* in memory instead of writing them to disk directly. 
* Return true on success, false on failure. 
*/ 
//bool sdbm_sync(); 

/** 
* Close database, synchronizing changes (if any). Return 
* true on success, false on failure. 
*/ 
bool sdbm_close() { // Errors: 5) Couldn't close database 
    if (fclose(db) == EOF) { 
    err = 5; 
    printf("Couldn't close database.\n"); 
    return false; 
    } 
    return true; 
} 
/** 
* Return error code for last failed database operation. 
*/ 
int sdbm_error() { 
    return err; 
} 

/** 
* Is given key in database? 
*/ 
//bool sdbm_has(const char *key); 

/** 
* Get value associated with given key in database. 
* Return true on success, false on failure. 
* 
* Precondition: sdbm_has(key) 
*/ 
//bool sdbm_get(const char *key, char *value); 

/** 
* Update value associated with given key in database 
* to given value. Return true on success, false on 
* failure. 
* 
* Precondition: sdbm_has(key) 
*/ 
//bool sdbm_put(const char *key, const char *value); 

/** 
* Insert given key and value into database as a new 
* association. Return true on success, false on 
* failure. 
* 
* Precondition: !sdbm_has(key) 
*/ 
//bool sdbm_insert(const char *key, const char *value); 

/** 
* Remove given key and associated value from database. 
* Return true on success, false on failure. 
* 
* Precondition: sdbm_has(key) 
*/ 
//bool sdbm_remove(const char *key); 

Répondre

4

La définition devrait être comme

typedef struct Key{ 
    char *name; 
    struct Key *next; // <-- Note `struct` here 
}Key; 

Vous ne pouvez pas utiliser juste Key [sans écrire explicitement struct avant qu'il] dans la définition de la structure, car la structure est pas encore définie [typedefed]

+0

Vous êtes le meilleur. Ça fonctionne maintenant. Je ne peux pas attendre que je connaisse C et ne fais pas ce genre d'erreur. –

+0

Une question, est-ce que cela change le type de prochaine? Est-ce maintenant une clé structur * ou est-ce encore une clé *? –

+0

@David Watson: C'est une 'clé de struct '. 'typdef' est simplement utilisé comme espace réservé/synonyme pour un autre type. –

1

Pendant que je suis creuser mon compilateur dehors, vous pouvez essayer de modifier les déclarations à:

typedef struct Key_ { 
    char *name; 
    struct Key_ *next; 
} Key; 

et laissez-nous savoir si cela aide? Je pense que vous utilisez le typedef avant qu'il ne soit déclaré.

+0

Mon compilateur ne s'en plaignait pas non plus - avec le nom de la balise struct, ou avec le typedef, l'une ou l'autre façon convenait. Il se plaignait d'un couple de void * cast, et que currKey était un tableau d'int et ne pouvait pas être assigné à un pointeur sur char. – jwismar

+1

Vous pouvez utiliser le même nom, pas besoin d'un suffixe de soulignement. –

+0

Assez juste. Il me vient à l'esprit qu'il y a un problème soit avec un ancien standard, soit avec une compatibilité croisée avec C++, où avoir le nom de la balise struct en conflit avec le typedef était un problème, alors quand j'écris C, j'ai tendance à utiliser style. Il se peut que ce soit périmé. – jwismar