record isn't added to file
Please look at the code below, it's going to save a simple contact address in a database file, but it's not working. My guess is that the database_add function(at the bottom of the code) is not working properly(especially I'm suspicious about this line: `conn->db->rows[addr->id] = *addr;`, but compiler gives no error. I'd be really grateful if someone takes a look.
compile, then run it like this:
1_ ./program dbname.db c
(c stands for "create")
2_ ./program dbname.db s 0 "john lee" [email protected]
database file is created but when I look into it I can't find the record.
thank you.
Code:
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define MAX_ROWS 250
#define MAX_DATA 100
struct Address{
int id;
int set;
char fullname[MAX_DATA];
char email[MAX_DATA];
};
struct Database{
struct Address rows[MAX_ROWS];
};
struct Connection{
FILE* file;
struct Database* db;
};
void die(char* msg);
void database_create(struct Connection*);
int database_write(struct Connection* conn);
struct Connection* database_open(char* dbname, char mode);
void database_close(struct Connection* conn);
void database_load(struct Connection* conn);
void database_add(struct Connection* conn, struct Address* addr);
//ex17 mydb.db c
int main(int argc, char** argv){
if(argc <= 2) {
puts("Either no database name(dbname) OR no command was determined.\n\tusage: <program> <dbname> <command_option> <arguments>");
exit(1);
}
char option;
char* dbname;
dbname = argv[1];
option = argv[2][0];
struct Connection* conn = database_open(dbname, option);
if(!conn) die("error opening the database");
switch(option){
case 'c':
database_create(conn);
database_write(conn);
break;
case 's':
if(argc < 6){
die("Error: Provide all fields of the record (id, fullname, email)");
}
struct Address addr = {.id=atoi(argv[3]),.fullname=argv[4],.email=argv[5]};
database_add(conn,&addr);
int test_success = database_write(conn);
if(test_success) puts("Record was added successfully.");
break;
default:
die("Bad usage!\n\tusage: <program> <dbname> <command_option> <arguments>\n\tcommand_option is one of these: c(create) l(list) g(get) s(set) d(delete)");
break;
}
database_close(conn);
return 0;
}
void die(char* msg){
if(errno){
perror(msg);
}else{
printf("Error: %s\n",msg);
}
exit(1);
}
int database_write(struct Connection* conn){
rewind(conn->file);
int writecount = fwrite(conn->db, sizeof(struct Database), 1, conn->file);
if(writecount!=1){
die("database write unsuccessful");
}
//flush
int rc = fflush(conn->file);
if (rc == -1)
die("Cannot flush database.");
return 1;
}
void database_create(struct Connection* conn){
for(int i=0; i<MAX_ROWS; i++){
struct Address addr = { .id=i , .set=0 };
conn->db->rows[i] = addr;
}
}
struct Connection* database_open(char* dbname, char mode){
struct Connection* conn;
conn = malloc(sizeof(struct Connection));
if(!conn){
die("memory error\n");
}
conn->db = malloc(sizeof(struct Database));
if(!conn){
die("memory error\n");
}
if(mode=='c'){
database_create(conn);
conn->file = fopen(dbname,"w");
}else{
conn->file = fopen(dbname,"r+");
if(conn->file){
database_load(conn);
}
}
return conn;
}
void database_load(struct Connection* conn){
if(!conn) die("a valid connection to database not found\n");
int readcount = fread(conn->db,sizeof(struct Database),1,conn->file);
if(readcount!=1) die("error in reading the database");
}
void database_close(struct Connection* conn){
if(conn){
if(conn->db){
free(conn->db);
}
if(conn->file){
fclose(conn->file);
}
free(conn);
}
}
//program s 1 "john lee" [email protected]
void database_add(struct Connection* conn, struct Address* addr){
if(!conn->db) die("No connection to database");
if(addr->id > MAX_ROWS) die("id is too big. id must be less than MAX_ROWS");
if(addr->set) die("This record is already set, delete it first");
addr->set = 1;
conn->db->rows[addr->id] = *addr;
}