C语言版:条件的组合

179 阅读3分钟

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)

源代码稍加修改,可以支持两种方式。