Permalink
Browse files

ex17, ex18, ex19

  • Loading branch information...
1 parent 2bd7550 commit b3f786e6e7fc10945c14afb41c3d80cc5d3e09d0 Sam Breed committed Feb 20, 2012
Showing with 678 additions and 1 deletion.
  1. +2 −1 Makefile
  2. +200 −0 ex17.c
  3. +109 −0 ex18.c
  4. +9 −0 ex19/Makefile
  5. +212 −0 ex19/ex19.c
  6. +46 −0 ex19/ex19.h
  7. +73 −0 ex19/object.c
  8. +27 −0 ex19/object.h
View
@@ -1,8 +1,9 @@
CFLAGS=-Wall -g
-SOURCES=ex1 ex4 ex6 ex7 ex8 ex9 ex10 ex11 ex12 ex13 ex14 ex15 ex16
+SOURCES=ex1 ex4 ex6 ex7 ex8 ex9 ex10 ex11 ex12 ex13 ex14 ex15 ex16 ex17 ex18
all: $(SOURCES)
clean:
rm -f $(SOURCES)
+ rm -f *.dat
rm -rf *.dSYM
View
@@ -0,0 +1,200 @@
+#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 Connection {
+ FILE *file;
+ struct Database *db;
+};
+
+void Database_close(struct Connection *conn)
+{
+ if(conn) {
+ if(conn->file) fclose(conn->file);
+ if(conn->db) free(conn->db);
+ free(conn);
+ }
+}
+
+void die(const char *message, struct Connection *conn)
+{
+ if(errno) {
+ perror(message);
+ } else {
+ printf("ERROR: %s\n", message);
+ }
+
+ Database_close(conn);
+
+ exit(1);
+}
+
+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);
+ if(rc != 1) die("Failed to load database", conn);
+}
+
+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(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_write(struct Connection *conn)
+{
+ rewind(conn->file);
+
+ int rc = fwrite(conn->db, sizeof(struct Database), 1, conn->file);
+ if(rc != 1) die("Failed to write to database", conn);
+
+ rc = fflush(conn->file);
+ if(rc == -1) die("Cannont flush database", conn);
+}
+
+void Database_create(struct Connection *conn)
+{
+ int i = 0;
+
+ for(i=0; i < MAX_ROWS; i++) {
+ // make a prototype & initialize 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", conn);
+
+ addr->set = 1;
+ // FIXME
+ char *res = strncpy(addr->name, name, MAX_DATA);
+ // demonstrate strncopy bug
+ if(!res) die("Name copy failed", conn);
+
+ res = strncpy(addr->email, email, MAX_DATA);
+ if(!res) die("Email copy failed", conn);
+}
+
+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", conn);
+ }
+}
+
+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: ex17 <dbfile> <action> [action params]", NULL);
+
+ 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]);
+ if(id >= MAX_ROWS) die("There's not that many records", conn);
+
+ switch(action) {
+ case 'c':
+ Database_create(conn);
+ Database_write(conn);
+ break;
+
+ case 'g':
+ if(argc != 4) die("Please provide an ID", conn);
+
+ Database_get(conn, id);
+ break;
+
+ case 's':
+ if(argc != 6) die("Need IF, name, email to set", conn);
+
+ Database_set(conn, id, argv[4], argv[5]);
+ Database_write(conn);
+ break;
+
+ case 'd':
+ if(argc != 4) die("Need id to delete", conn);
+
+ Database_delete(conn, id);
+ Database_write(conn);
+ break;
+
+ case 'l':
+ Database_list(conn);
+ break;
+ default:
+ die("Invailid action, only c=create, g=get, s=set, d=del, l=list", conn);
+ }
+
+ Database_close(conn);
+
+ return 0;
+}
View
@@ -0,0 +1,109 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+void die(const char *message)
+{
+ if(errno) {
+ perror(message);
+ } else {
+ printf("Error: %s\n", message);
+ }
+
+ exit(1);
+}
+
+// a typedef creates a faky type, in this case for a function pointer
+typedef int(*compare_cb)(int a, int b);
+
+/**
+ * A classic bubble sort function that uses the
+ * compare_cb fn to do the sorting
+ */
+int *bubble_sort(int *numbers, int count, compare_cb cmp)
+{
+ int temp = 0;
+ int i = 0;
+ int j = 0;
+ int *target = malloc(count * sizeof(int));
+
+ if(!target) die("Memory Error");
+
+ memcpy(target, numbers, count * sizeof(int));
+
+ for(i = 0; i < count; i++) {
+ for(j = 0; j < count - 1; j++) {
+ if(cmp(target[j], target[j+1]) > 0) {
+ temp = target[j+1];
+ target[j+1] = target[j];
+ target[j] = temp;
+ }
+ }
+ }
+
+ return target;
+}
+
+int sorted_order(int a, int b)
+{
+ return a - b;
+}
+
+int reverse_order(int a, int b)
+{
+ return b - a;
+}
+
+int strange_order(int a, int b)
+{
+ if(a == 0 || b == 0) {
+ return 0;
+ } else {
+ return a % b;
+ }
+}
+
+/**
+ * Used to test that we are sorting things correctly
+ * by doing the sort and printing it out.
+ */
+void test_sorting(int *numbers, int count, compare_cb cmp)
+{
+ int i = 0;
+ int *sorted = bubble_sort(numbers, count, cmp);
+
+ if(!sorted) die("Failed to sort as requested");
+
+ for(i = 0; i < count; i++) {
+ printf("%d ", sorted[i]);
+ }
+ printf("\n");
+
+ free(sorted);
+}
+
+int main(int argc, char *argv[])
+{
+ if(argc < 2) die("Usage: ex18 4 3 1 5 6");
+
+ int count = argc - 1;
+ int i = 0;
+ char **inputs = argv + 1;
+
+ int *numbers = malloc(count * sizeof(int));
+ if(!numbers) die("Memory error.");
+
+ for(i = 0; i < count; i++) {
+ numbers[i] = atoi(inputs[i]);
+ }
+
+ test_sorting(numbers, count, sorted_order);
+ test_sorting(numbers, count, reverse_order);
+ test_sorting(numbers, count, strange_order);
+
+ free(numbers);
+
+ return 0;
+}
View
@@ -0,0 +1,9 @@
+CFLAGS=-Wall -g
+
+all: ex19
+
+ex19: object.o
+
+clean:
+ rm -f ex19
+ rm -f *.o
Oops, something went wrong.

0 comments on commit b3f786e

Please sign in to comment.