2012-09-21 59 views
0
gcc (GCC) 4.7.0 
c89 

你好,使用FWRITE和FREAD保存和檢索樣本malloc分配數據庫

我已經試圖行的數據庫保存到使用fwrite來寫和檢索文件(db.dat)它使用fread。但是,當我用fread進行檢索時,數據是空的。

我不確定在獲取數據之前是否應該malloc一些內存。我在我的例子中嘗試過的內容

這裏我沒有顯示空閒內存,因爲這只是代碼片段。

非常感謝您的任何建議,

This is my structure of the database: 
struct address { 
    int id; 
    int set; 
    char *name; 
    char *email; 
}; 

struct database { 
    struct address **rows; 
    size_t data_size; 
    size_t max_size; 
}; 

struct connection { 
    FILE *fp; 
    struct database *db; 
}; 

數據庫開放:

struct connection* database_open(const char *filename, char mode) 
{ 
    struct connection *conn = NULL; 

    conn = malloc(sizeof(struct connection)); 

    conn->db = malloc(sizeof(struct database)); 
    if(conn->db == NULL) { 
     log_exit("Memory error allocating database", conn); 
    } 

    if(conn == NULL) { 
     log_exit("Memory error allocating connection", conn); 
    } 

    printf("Create a new database\n"); 
    conn->fp = fopen(filename, "w"); 

    if(conn->fp == NULL) { 
     log_exit("Failed to open file", conn); 
    } 

    return conn; 
} 

創建數據庫:

void database_create(struct connection *conn, int _max_size, int _data_size) 
{ 
    int i = 0; 
    struct address *db_row = NULL; 

    /* Set the size of the database by assigning the max number of database rows */ 
    conn->db->max_size = _max_size; 
    conn->db->data_size = _data_size; 

    /* Allocate memory for rows and size */ 
    conn->db->rows = malloc(sizeof(struct address) * _max_size); 
    if(!conn->db->rows) { 
     log_exit("Memory error alocating rows", conn); 
    } 

    for(i = 0; i < _max_size; i++) { 
     db_row = malloc(sizeof(struct address)); 

     db_row->id = i; 
     db_row->set = 0; 
     db_row->name = malloc(_data_size); 
     db_row->email = malloc(_data_size); 

     /* Add the row to the database */ 
     conn->db->rows[i] = db_row; 
    } 
} 

編寫數據庫

void database_write(struct connection *conn) 
{ 
    rewind(conn->fp); 

    if(fwrite(conn->db, sizeof(struct database), 1, conn->fp) != 1) { 
     log_exit("Failed to write to database.", conn); 
    } 

    if(fflush(conn->fp) != 0) 
    { 
     log_exit("Cannot flush database.", conn); 
    } 
} 

然後我打開數據庫r +並使用fread。但是,我在id和set變量中設置的數據是空的。

void database_load(struct connection *conn) 
{ 
    /* Clear any errors from file pointer */ 
    clearerr(conn->fp); 

    /* I have had to hack this just so that I can get the 
     memory allocated before filling the structure not sure if this is the best way */ 
    conn->db->rows = malloc(sizeof(struct address) * 1); /* This would be set to how many rows I have - just experimenting with just one */ 
    conn->db->rows[0] = malloc(sizeof(struct address)); 
    conn->db->rows[0]->name = malloc(20); 
    conn->db->rows[0]->email = malloc(20); 

    if(fread(conn->db, sizeof(struct database), 1, conn->fp) != 1) { 
     if(feof(conn->fp) != 0) { 
      log_exit("Database end of file", conn); 
     } 

     if(ferror(conn->fp) != 0) { 
      log_exit("Database cannot open", conn); 
     } 
    }  
} 

====編輯===

int main(int argc, char **argv) 
{ 
    char *filename = NULL; 
    char action = 0; 
    int id = 0; 
    int rows = 0; 
    int size = 0; 
    struct connection *conn = NULL; 

    if(argc < 3) { 
     log_exit("USAGE: ex17 <dbfile> <action> [ action params ]", conn); 
    } 

    filename = argv[1]; 
    action = argv[2][0]; 
    rows = atoi(argv[3]); 
    size = atoi(argv[4]); 

    conn = database_open(filename, action); 

    if(argc > 3) { 
     id = atoi(argv[3]); 
    } 

    switch(action) { 
    case 'c': 
     database_create(conn, rows, size); 
     database_write(conn); 
     break; 

    case 's': 
     if(argc != 6) { 
      log_exit("Need id, name, email to set", conn); 
     } 

     database_set(conn, id, argv[4], argv[5]); 
     database_write(conn); 
     break; 

    default: 
     log_exit("Invalid action, only: c = create, g = get, d = del, l = list", conn); 
    } 

    database_close(conn); 

    return 0; 
} 
+0

請問'database_set'實際上正確設置值是多少? –

+0

我不能那麼遠。因爲我需要使用fread打開數據庫。因爲我做不到這一點,所以我不能再去解決這個問題。謝謝。 – ant2009

+0

對不起,您需要先寫信給您的文件,然後才能讀取它。另外我也沒有看到你的代碼在你的代碼中調用了'database_load',所以我不知道你在做什麼。 –

回答

1

看着你rows是一個雙指針,你需要與sizeof(pointer*)初始化第一指針,這樣的:

conn->db->rows = malloc(sizeof(struct address) * 1); 

應該是:

conn->db->rows = malloc(sizeof(struct address*)); //notice how struct address becomes struct address* 

同樣的,這樣的:

conn->db->rows = malloc(sizeof(struct address) * _max_size); 

應該是:

conn->db->rows = malloc(sizeof(struct address*) * _max_size); 
+0

完成這些更改後。我仍然有同樣的問題。在fread之後,set和id仍然是零。沒有真正做出任何不同。謝謝。該id會根據我想要的行數增加。但是,這沒有做到這一點。非常感謝您提供更多建議。 – ant2009

+0

你有沒有通過它與調試器? –

+0

您是否創建了相同數量的行來讀回數據,而不是首先寫入數據庫文件? –