2.1可变的需求被参数化中,要求完成实验:输出0-x之间符合“某种”条件的数。
在例程2-1中,完成了实验4的C语言版的单一条件测试.
// filter.c文件
#include <stdio.h>
#include <stdbool.h>
typedef _Bool (*Test)(int); //函数指针
void filter (int x,Test test) {
for (int i = 0; i < x; i++) {
if (test(i)) {
printf("%d ",i);
}
}
}//头文件ood.h 略
//main.c文件(头文件 略)
#include "ood.h"
#include <stdbool.h>
_Bool isMultipleOf3(int n) { //n 是否3的倍数
return (n % 3 == 0);
} //其他可能需要的条件函数 略
int main(void){
filter (100, &isMultipleOf3);
return 0;
}
如果filter需要进行多种条件的测试,例如过滤出3的倍数“而且”含5的数,Java、Scheme等语言支持闭包/嵌套函数,Java中设计接口Condition可以提供and(Condition)、or(Condition)和not()方法。
filter(100, c.and(n -> (n % 3 == 0))); //Java中Condition的用法。
但是,由于C语言不支持嵌套函数,就无法提供and(Test test)、or(Test test)和not(Test test)方法。
1.流水线操作和逐一测试操作
当用户要使用多个Test函数并加以and、or、not组合时,可以将每一步操作作为链表struct condition/Cond的结点,它们构成一个操作的流水线。而_Bool test(int n,Cond* head)将使用该链表完成对某一个数n的组合判断,当处理0-x之间符合组合条件的数时,将对0-x之间的数进行逐一的测试操作。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef _Bool (*Test)(int); //函数指针
typedef struct condition{
Test test;
char* op;
struct condition *next;
}Cond;
Cond* new(Test test){
Cond* p=NULL;
p= (Cond*)malloc(sizeof(Cond));
p->test = test;
p->op="";
p->next =NULL;
return p;
}
Cond* op_Cond(Cond* head,Test test,char* op){
Cond* p = head;
while (p->next!= NULL){
p = p->next;
}
p->op=op;
Cond* next =new(test);
p->next =next;
return head;
}
Cond* and(Cond* head,Test test){
return op_Cond(head,test,"and");
}
Cond* or(Cond* head,Test test){
return op_Cond(head,test,"or");
}
Cond* not(Cond* head,Test test){
return op_Cond(head,test,"not");
}
_Bool test(int n,Cond* head){
_Bool result= head->test(n);
if(head->op == ""){//单一测试
return head->test(n);
}
while (head->next!= NULL){
char* op = head->op;
if(op == "and") result = result && head->next->test(n);
else if (op == "or")result = result||head->next->test(n);
else if (op == "not")result = result&& !head->next->test(n);
head = head->next;
}
return result;
}
void filter3(int x, Cond* head){
for (int i = 0; i < x; i++) {
if (test(i,head)){
printf("%d ", i);
}
}
}
void free_Cond(Cond* head){
while (head->next!= NULL){
Cond* p = head;
head = head->next;
free(p);
}
}
////ood.h
// for filter.c
typedef _Bool (*Test)(int); //函数指针
void filter (int x,Test test);
typedef struct cond{
Test test;
char* op;
struct cond *next;
}Cond;
Cond* new(Test test);
Cond* and(Cond* head,Test test);
Cond* or (Cond* head,Test test);
Cond* not(Cond* head,Test test);
void filter2(int x, Cond* head);
void free_Cond(Cond* head);
测试代码:is3x (int n) //n 是否3的倍数,等等。
#include "ood.h"
#include <stdio.h>
_Bool is3x (int n) { //n 是否3的倍数
return (n % 3 == 0);
}//其他略
void testCond(void){
Cond* c = new(&is3x);
filter3(30,c);
printf("\n");
filter3(100,and(c,&is5x)); //0 15 30 45 60 75 90
printf("\n");
filter3(100,or( c,&is33x));//0 15 30 33 45 60 66 75 90 99
free_Cond(c);//释放
printf("\n");
c = new(&is3x);
filter3(100,or( and(c,&is5x),&is33x));//比较
free_Cond(c);
printf("\n");
c = new(&is3x);
filter3(100,not(or( and(c,&is5x),&is33x),is10x));
free_Cond(c);
printf("\n");
}
输出: 0 3 6 9 12 15 18 21 24 27
0 15 30 45 60 75 90
0 15 30 33 45 60 66 75 90 99
0 15 30 33 45 60 66 75 90 99
15 33 45 66 75 99
一个问题,Cond的组合,你更喜欢另一种方式:
not( or( and(c,&is5x), &is33x),is10x)
与
c->and(c,&is5x)->or(c,&is33x)->not(c,is10x)
源代码稍加修改,可以支持两种方式。