所以我目前正在学习 C the Hard Way并坚持练习 17 中的额外学分。
需要将固定大小的数据库从http://c.learncodethehardway.org/book/ex17.html转换为动态大小的数据库,您可以在其中获取用户允许的行数和最大字符串长度。
我设法让程序创建数据库并将其写入文件,但是我无法弄清楚如何再次从文件中读取程序。
该程序正在编译,但每当我尝试执行除创建数据库之外的任何操作时,它都会出现段错误。我已经检查了 valgrind,直接原因似乎是从未分配的内存中读取。我相信问题出在下面的 Database_load 函数中。
请注意,这是我第一次发布问题,如果我发布太多,请道歉。
加载它:
struct Connection *Database_open(const char *filename, char mode)
{
struct Connection *conn = malloc(sizeof(struct Connection));
if(!conn) die("Memory error", conn);
conn->db = malloc(sizeof(struct Database));
if(!conn->db) die("Memory error", conn);
// If we're creating, write a new file otherwise load it up.
if(mode == 'c') {
conn->file = fopen(filename, "w");
} else {
conn->file = fopen(filename, "r+");
if(conn->file) {
Database_load(conn);
}
}
if(!conn->file) die("Failed to open the file", conn);
return conn;
}
void Database_load(struct Connection *conn)
{
int rc = fread(conn->db, sizeof(struct Database), 1, conn->file);
if(rc != 1) die("Failed to load database.", conn);
const int MAX_ROWS = conn->db->MAX_ROWS;
const int MAX_DATA = conn->db->MAX_DATA;
int i = 0;
// I want to allocate memory for the rows and the strings here...
// Clearly the freads are failing, how would I actually allocate properly?
for(i = 0; i < MAX_ROWS; i++) {
rc = fread(conn->db->rows, sizeof(struct Address),
1 , conn->file);
if(rc != 1) die("Failed to load rows.", conn);
rc = fread(&conn->db->rows[i], sizeof(char),
MAX_DATA, conn->file);
if(rc != MAX_DATA) die("Failed to load characters.", conn);
}
以下补充资料:
涉及的结构:
struct Address {
int id;
int set;
char *name;
char *email;
};
struct Database {
int MAX_DATA;
int MAX_ROWS;
struct Address *rows;
};
struct Connection {
FILE *file;
struct Database *db;
};
创建数据库:
void Database_create(struct Connection *conn, const int MAX_ROWS, const int MAX_DATA)
{
int i = 0;
conn->db->MAX_ROWS = MAX_ROWS;
conn->db->MAX_DATA = MAX_DATA;
conn->db->rows = (struct Address *)malloc(sizeof(struct Address)*MAX_ROWS);
for(i = 0; i < MAX_ROWS; i++) {
struct Address addr;
addr.id = i;
addr.set = 0;
addr.name = (char *)malloc(sizeof(char)*MAX_DATA);
addr.email = (char *) malloc(sizeof(char)*MAX_DATA);
conn->db->rows[i] = addr;
}
}
最后,清理:
void Database_close(struct Connection *conn)
{
int i = 0;
struct Address *cur_row = NULL;
if(conn) {
if(conn->file) fclose(conn->file);
if(conn->db) {
if(conn->db->rows) {
for(i = 0; i < conn->db->MAX_ROWS; i++) {
cur_row = &conn->db->rows[i];
if(cur_row) {
free(cur_row->name);
free(cur_row->email);
}
}
free(conn->db->rows);
}
free(conn->db);
}
free(conn);
}
}