Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include<stdio.h>
- #include<assert.h>
- #include<stdlib.h>
- #include<errno.h>
- #include<string.h>
- #define MAX_DATA 512
- #define MAX_ROWS 100
- struct Address{
- int id;
- int set;
- char name[MAX_DATA];
- char email[MAX_DATA];
- };
- struct Database{
- struct Address rows[MAX_ROWS];// struct within struct rows of Address.
- };
- struct Connection{
- FILE *file;
- struct Database *db;
- };
- void die (const char *message){
- if(errno){
- perror(message);
- }else{
- printf("ERROR:%s\n",message);
- }
- exit(1);// Check this out!
- }
- void Address_print(struct Address *addr){
- printf("%d %s %s\n",addr->id,addr->name,addr->email);
- }
- void Database_load(struct Connection *conn){
- int rc=fread(conn->db,sizeof(struct Database),1,conn->file);// important line,fread is new!
- if(rc!=1)die("Failed to load database");
- }
- struct Connection* Database_open(const char *filename,char mode){// check if Connection* or Connection *Database
- struct Connection *conn=malloc(sizeof(struct Connection));
- if(!conn) die("Memory Error");
- conn->db=malloc(sizeof(struct Database));
- if(!conn->db) die("Memory Error");
- 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");
- return conn;
- }
- void Database_close(struct Connection *conn){
- if(conn){
- if(conn->file)fclose(conn->file);
- if(conn->db) free(conn->db);
- free(conn);
- }
- }
- void Database_write(struct Connection *conn){
- rewind(conn->file);//New- word:rewind???
- int rc=fwrite(conn->db,sizeof(struct Database),1,conn->file);
- if(rc!=1)die("Failed to write database.");
- rc=fflush(conn->file);
- if(rc==-1)die("Cannot flush database!");
- }
- void Database_create(struct Connection *conn){
- int i=0;
- for(i=0;i<MAX_ROWS;i++){
- //make a prototype to initialise it.
- struct Address addr={.id=i,.set=0};
- // then just assign it
- conn->db->rows[i]=addr;
- }
- }
- void Database_set(struct Connection *conn, int id,const char *name,const char *email){
- struct Address *addr=&conn->db->rows[id];
- if(addr->set)die("Already set,delete it first");
- addr->set=1;
- // WARNING:bug, read the "How to Break It" and fix this!
- char *res= strncpy(addr->name,name,MAX_DATA);//new key!!
- //demonstrate the strncpy bug!
- if(!res) die("Name copy failed!");
- res=strncpy(addr->email,email,MAX_DATA);
- if(!res)die("Email copy failed");
- }
- void Database_get(struct Connection *conn, int id){
- struct Address *addr=&conn->db->rows[id];
- if(addr->set){
- Address_print(addr);
- }else{
- die("ID is not set");
- }
- }
- void Database_delete(struct Connection *conn, int id){
- struct Address addr={.id=id,.set=0};
- conn->db->rows[id]=addr;
- }
- void Database_list(struct Connection *conn){
- int i=0;
- struct Database *db=conn->db;
- for (i=0;i<MAX_ROWS;i++){
- struct Address *cur=&db->rows[i];
- if(cur->set){
- Address_print(cur);
- }
- }
- }
- int main(int argc,char *argv[]){
- if (argc<3)die("USAGE ex 17<dbfile> <action >[action params]");
- char *filename=argv[1];
- char action=argv[2][0];
- struct Connection *conn=Database_open(filename,action);
- int id=0;
- if (argc>3)id=atoi(argv[3]);// Convert String to number.
- if(id>=MAX_ROWS)die("There aren't that many records!");
- switch(action){
- case 'c':
- Database_create(conn);
- Database_write(conn);
- break;
- case 'g':
- if(argc!=4)die("Need an id to get");
- Database_get(conn,id);
- break;
- case 's':
- if(argc!=6) die("Need id, name,email to set");
- Database_set(conn,id,argv[4],argv[5]);
- Database_write(conn);
- break;
- case 'l':
- Database_list(conn);
- break;
- default:
- die("Invalid action,only:c=create,g=get,s=set,d=del,l=list");
- }
- Database_close(conn);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement