// warning: this code has not been run; it may have small bugs #include #define TRUE 1 #define FALSE 0 typedef int bool; typedef struct IntList* list_t; struct IntList { int val; list_t tail; }; // the old boring way (not as flexible) bool find0(list_t lst, int x) { for(; lst != NULL; lst = lst->tail) if(lst->val == x) return TRUE; return FALSE; } bool has_seventeen0(list_t lst) { return find0(lst,17); } bool has_nineteen0(list_t lst) { return find0(lst,19); } // not as useful because functions aren't passed "private state" bool find1(list_t lst, bool (*f)(int)) { for(; lst != NULL; lst = lst->tail) if(f(lst->val)) return TRUE; return FALSE; } bool is_seventeen(int x) { return x==17; } bool is_nineteen(int x) { return x==19; } bool is_five_bits(int x) { return x >= (1 << 4) && x < (1 << 5); } bool is_seven_bits(int x) { return x >= (1 << 6) && x < (1 << 7); } bool has_seventeen(list_t lst) { return find1(lst,is_seventeen); } bool has_nineteen(list_t lst) { return find1(lst,is_nineteen); } bool has_five_bits(list_t lst) { return find1(lst,is_five_bits); } bool has_seven_bits(list_t lst) { return find1(lst,is_seven_bits); } // begin of ugly code -- don't do it though it works here int num; // global variable bool is_num(int x) { return x==num; } bool has_n(list_t lst, int n) { num = n; return find1(lst,is_num); } int bits; // global variable bool is_bits(int x) { return x >= (1 << (bits-1)) && x < (1 << bits); } bool has_bits(list_t lst, int b) { bits = b; return find1(lst,is_bits); } // this code is ugly _and_ WRONG (not on the exam) typedef bool (*int_to_bool_fun_t) (int); int_to_bool_fun_t make_is_n(int n) { // fundamentally broken num = n; return is_num; } int_to_bool_fun_t f1; // global variable int_to_bool_fun_t f2; // global variable bool or_int(int x) { return f1(x) || f2(x); } bool or_list(list_t lst, int_to_bool_fun_t fun1, int_to_bool_fun_t fun2) { f1 = fun1; f2 = fun2; return find1(lst,or_int); } bool has_three_or_seven(list_t lst) { // shows why make_is_n is broken return or_list(lst, make_is_n(3), make_is_n(7)); } // this version of find makes it pretty convenient for functions to // have data to play with bool find2(list_t lst, void* state, bool(*f)(void*,int)) { for(; lst != NULL; lst = lst->tail) if(f(state,lst->val)) return TRUE; return FALSE; } bool is_nineteen2(void* ignore, int x) { return x == 19; } bool has_nineteen2(list_t lst) { return find2(lst,NULL,is_nineteen2); } bool is_num2(void * p, int x) { int n = *((int*)p); return n==x; } bool has_n2(list_t lst, int n) { return find2(lst,&n,is_num2); } // and some fancy code that does or correctly (not on the exam) typedef bool (*int_to_bool_fun2_t)(void*,int); struct OrState { void* state1; int_to_bool_fun2_t f1; void* state2; int_to_bool_fun2_t f2; }; bool or_int2(void* orstate, int x) { struct OrState * s = (struct OrState*)orstate; return s->f1(s->state1, x) || s->f2(s->state2, x); } bool or_list2(list_t lst, void* state1, int_to_bool_fun2_t f1, void* state2, int_to_bool_fun2_t f2) { struct OrState s; s.state1 = state1; s.state2 = state2; s.f1 = f1; s.f2 = f2; return find2(lst,&s,or_int2); } bool has_three_or_seven2(list_t lst) { int i1 = 3; int i2 = 7; return or_list2(lst,&i1,is_num2,&i2,is_num2); }