⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 graph.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include <u.h>#include <libc.h>#include <stdio.h>#include "iplot.h"#define	INF	1.e+37#define	F	.25struct xy {	int	xlbf;		/*flag:explicit lower bound*/	int 	xubf;		/*flag:explicit upper bound*/	int	xqf;		/*flag:explicit quantum*/	double (*xf)(double);	/*transform function, e.g. log*/	float	xa,xb;		/*scaling coefficients*/	float	xlb,xub;	/*lower and upper bound*/	float	xquant;		/*quantum*/	float	xoff;		/*screen offset fraction*/	float	xsize;		/*screen fraction*/	int	xbot,xtop;	/*screen coords of border*/		float	xmult;		/*scaling constant*/} xd,yd;struct val {	float xv;	float yv;	int lblptr;} *xx;char *labels;int labelsiz;int tick = 50;int top = 4000;int bot = 200;float absbot;int	n;int	erasf = 1;int	gridf = 2;int	symbf = 0;int	absf = 0;int	transf;int	equf;int	brkf;int	ovlay = 1;float	dx;char	*plotsymb;#define BSIZ 80char	labbuf[BSIZ];char	titlebuf[BSIZ];char *modes[] = {	"disconnected",	"solid",	"dotted",	"dotdashed",	"shortdashed",	"longdashed"};int mode = 1;double ident(double x){	return(x);}struct z {	float lb,ub,mult,quant;};struct {	char *name;	int next;} palette[] = {	['b']	{ "blue", 'b' },	['c']	{ "cyan", 'c' },	['g']	{ "green", 'g' },	['k']	{ "kblack", 'k' },	['m']	{ "magenta", 'm' },	['r']	{ "red", 'r' },	['w']	{ "white", 'w' },	['y']	{ "yellow", 'y' }};int pencolor = 'k';void init(struct xy *);void setopt(int, char *[]);void readin(void);void transpose(void);void getlim(struct xy *, struct val *);void equilibrate(struct xy *, struct xy *);void scale(struct xy *);void limread(struct xy *, int *, char ***);int numb(float *, int *, char ***);void colread(int *, char ***);int copystring(int);struct z setloglim(int, int, float, float);struct z setlinlim(int, int, float, float);void axes(void);int setmark(int *, struct xy *);void submark(int *, int *, float, struct xy *);void plot(void);int getfloat(float *);int getstring(void);void title(void);void badarg(void);int conv(float, struct xy *, int *);int symbol(int, int, int);void axlab(char, struct xy *, char *);void main(int argc,char *argv[]){	openpl();	range(0,0,4096,4096);	init(&xd);	init(&yd);	xd.xsize = yd.xsize = 1.;	xx = (struct val *)malloc((unsigned)sizeof(struct val));	labels = malloc(1);	labels[labelsiz++] = 0;	setopt(argc,argv);	if(erasf)		erase();	readin();	transpose();	getlim(&xd,(struct val *)&xx->xv);	getlim(&yd,(struct val *)&xx->yv);	if(equf) {		equilibrate(&xd,&yd);		equilibrate(&yd,&xd);	}	scale(&xd);	scale(&yd);	axes();	title();	plot();	closepl();	exits(0);}void init(struct xy *p){	p->xf = ident;	p->xmult = 1;}void setopt(int argc, char *argv[]){	char *p1, *p2;	float temp;	xd.xlb = yd.xlb = INF;	xd.xub = yd.xub = -INF;	while(--argc > 0) {		argv++;again:		switch(argv[0][0]) {		case '-':			argv[0]++;			goto again;		case 'l': /* label for plot */			p1 = titlebuf;			if (argc>=2) {				argv++;				argc--;				p2 = argv[0];				while (*p1++ = *p2++);			}			break;		case 'd':	/*disconnected,obsolete option*/		case 'm': /*line mode*/			mode = 0;			if(!numb(&temp,&argc,&argv))				break;			if(temp>=sizeof(modes)/sizeof(*modes))				mode = 1;			else if(temp>=-1)				mode = temp;			break;		case 'o':			if(numb(&temp,&argc,&argv) && temp>=1)				ovlay = temp;			break;		case 'a': /*automatic abscissas*/			absf = 1;			dx = 1;			if(!numb(&dx,&argc,&argv))				break;			if(numb(&absbot,&argc,&argv))				absf = 2;			break;		case 's': /*save screen, overlay plot*/			erasf = 0;			break;		case 'g': /*grid style 0 none, 1 ticks, 2 full*/			gridf = 0;			if(!numb(&temp,&argc,&argv))				temp = argv[0][1]-'0';	/*for caompatibility*/			if(temp>=0&&temp<=2)				gridf = temp;			break;		case 'c': /*character(s) for plotting*/			if(argc >= 2) {				symbf = 1;				plotsymb = argv[1];				argv++;				argc--;			}			break;		case 't':	/*transpose*/			transf = 1;			break;		case 'e':	/*equal scales*/			equf = 1;			break;		case 'b':	/*breaks*/			brkf = 1;			break;		case 'x':	/*x limits */			limread(&xd,&argc,&argv);			break;		case 'y':			limread(&yd,&argc,&argv);			break;		case 'h': /*set height of plot */			if(!numb(&yd.xsize, &argc,&argv))				badarg();			break;		case 'w': /*set width of plot */			if(!numb(&xd.xsize, &argc, &argv))				badarg();			break;		case 'r': /* set offset to right */			if(!numb(&xd.xoff, &argc, &argv))				badarg();			break;		case 'u': /*set offset up the screen*/			if(!numb(&yd.xoff,&argc,&argv))				badarg();			break;		case 'p': /*pen color*/			colread(&argc, &argv);			break;		default:			badarg();		}	}}void limread(struct xy *p, int *argcp, char ***argvp){	if(*argcp>1 && (*argvp)[1][0]=='l') {		(*argcp)--;		(*argvp)++;		p->xf = log10;	}	if(!numb(&p->xlb,argcp,argvp))		return;	p->xlbf = 1;	if(!numb(&p->xub,argcp,argvp))		return;	p->xubf = 1;	if(!numb(&p->xquant,argcp,argvp))		return;	p->xqf = 1;}isdigit(char c){	return '0'<=c && c<='9';}numb(float *np, int *argcp, char ***argvp){	char c;	if(*argcp <= 1)		return(0);	while((c=(*argvp)[1][0]) == '+')		(*argvp)[1]++;	if(!(isdigit(c) || c=='-'&&(*argvp)[1][1]<'A' || c=='.'))		return(0);	*np = atof((*argvp)[1]);	(*argcp)--;	(*argvp)++;	return(1);}void colread(int *argcp, char ***argvp){	int c, cnext;	int i, n;	if(*argcp<=1)		return;	n = strlen((*argvp)[1]);	if(strspn((*argvp)[1], "bcgkmrwy")!=n)		return;	pencolor = cnext = (*argvp)[1][0];	for(i=0; i<n-1; i++){		c = (unsigned char)(*argvp)[1][i];		cnext = (unsigned char)(*argvp)[1][i+1];		palette[c].next = cnext;	}	palette[cnext].next = pencolor;	(*argcp)--;	(*argvp)++;}void readin(void){	int i, t;	struct val *temp;	if(absf==1) {		if(xd.xlbf)			absbot = xd.xlb;		else if(xd.xf==log10)			absbot = 1;	}	for(;;) {		temp = (struct val *)realloc((char*)xx,			(unsigned)(n+ovlay)*sizeof(struct val));		if(temp==0)			return;		xx = temp;		if(absf)			xx[n].xv = n*dx/ovlay + absbot;		else			if(!getfloat(&xx[n].xv))				return;		t = 0;	/* silence compiler */		for(i=0;i<ovlay;i++) {			xx[n+i].xv = xx[n].xv;			if(!getfloat(&xx[n+i].yv))				return;			xx[n+i].lblptr = -1;			t = getstring();			if(t>0)				xx[n+i].lblptr = copystring(t);			if(t<0 && i+1<ovlay)				return;		}		n += ovlay;		if(t<0)			return;	}}void transpose(void){	int i;	float f;	struct xy t;	if(!transf)		return;	t = xd; xd = yd; yd = t;	for(i= 0;i<n;i++) {		f = xx[i].xv; xx[i].xv = xx[i].yv; xx[i].yv = f;	}}int copystring(int k){	char *temp;	int i;	int q;	temp = realloc(labels,(unsigned)(labelsiz+1+k));	if(temp==0)		return(0);	labels = temp;	q = labelsiz;	for(i=0;i<=k;i++)		labels[labelsiz++] = labbuf[i];	return(q);}float modceil(float f, float t){	t = fabs(t);	return(ceil(f/t)*t);}floatmodfloor(float f, float t){	t = fabs(t);	return(floor(f/t)*t);}void getlim(struct xy *p, struct val *v){	int i;	i = 0;	do {		if(!p->xlbf && p->xlb>v[i].xv)			p->xlb = v[i].xv;		if(!p->xubf && p->xub<v[i].xv)			p->xub = v[i].xv;		i++;	} while(i < n);}void setlim(struct xy *p){	float t,delta,sign;	struct z z;	int mark[50];	float lb,ub;	int lbf,ubf;	lb = p->xlb;	ub = p->xub;	delta = ub-lb;	if(p->xqf) {		if(delta*p->xquant <=0 )			badarg();		return;	}	sign = 1;	lbf = p->xlbf;	ubf = p->xubf;	if(delta < 0) {		sign = -1;		t = lb;		lb = ub;		ub = t;		t = lbf;		lbf = ubf;		ubf = t;	}	else if(delta == 0) {		if(ub > 0) {			ub = 2*ub;			lb = 0;		} 		else			if(lb < 0) {				lb = 2*lb;				ub = 0;			} 			else {				ub = 1;				lb = -1;			}	}	if(p->xf==log10 && lb>0 && ub>lb) {		z = setloglim(lbf,ubf,lb,ub);		p->xlb = z.lb;		p->xub = z.ub;		p->xmult *= z.mult;		p->xquant = z.quant;		if(setmark(mark,p)<2) {			p->xqf = lbf = ubf = 1;			lb = z.lb; ub = z.ub;		} else			return;	}	z = setlinlim(lbf,ubf,lb,ub);	if(sign > 0) {		p->xlb = z.lb;		p->xub = z.ub;	} else {		p->xlb = z.ub;		p->xub = z.lb;	}	p->xmult *= z.mult;	p->xquant = sign*z.quant;}struct zsetloglim(int lbf, int ubf, float lb, float ub){	float r,s,t;	struct z z;	for(s=1; lb*s<1; s*=10) ;	lb *= s;	ub *= s;	for(r=1; 10*r<=lb; r*=10) ;	for(t=1; t<ub; t*=10) ;	z.lb = !lbf ? r : lb;	z.ub = !ubf ? t : ub;	if(ub/lb<100) {		if(!lbf) {			if(lb >= 5*z.lb)				z.lb *= 5;			else if(lb >= 2*z.lb)				z.lb *= 2;		}		if(!ubf) {			if(ub*5 <= z.ub)				z.ub /= 5;			else if(ub*2 <= z.ub)				z.ub /= 2;		}	}	z.mult = s;	z.quant = r;	return(z);}struct zsetlinlim(int lbf, int ubf, float xlb, float xub){	struct z z;	float r,s,delta;	float ub,lb;loop:	ub = xub;	lb = xlb;	delta = ub - lb;	/*scale up by s, a power of 10, so range (delta) exceeds 1*/	/*find power of 10 quantum, r, such that delta/10<=r<delta*/	r = s = 1;	while(delta*s < 10)		s *= 10;	delta *= s;	while(10*r < delta)		r *= 10;	lb *= s;	ub *= s;	/*set r=(1,2,5)*10**n so that 3-5 quanta cover range*/	if(r>=delta/2)		r /= 2;	else if(r<delta/5)		r *= 2;	z.ub = ubf? ub: modceil(ub,r);	z.lb = lbf? lb: modfloor(lb,r);	if(!lbf && z.lb<=r && z.lb>0) {		xlb = 0;		goto loop;	}	else if(!ubf && z.ub>=-r && z.ub<0) {		xub = 0;		goto loop;	}	z.quant = r;	z.mult = s;	return(z);}void scale(struct xy *p){	float edge;	setlim(p);	edge = top-bot;	p->xa = p->xsize*edge/((*p->xf)(p->xub) - (*p->xf)(p->xlb));	p->xbot = bot + edge*p->xoff;	p->xtop = p->xbot + (top-bot)*p->xsize;	p->xb = p->xbot - (*p->xf)(p->xlb)*p->xa + .5;}void equilibrate(struct xy *p, struct xy *q){	if(p->xlbf||	/* needn't test xubf; it implies xlbf*/	   q->xubf&&q->xlb>q->xub)		return;	if(p->xlb>q->xlb) {		p->xlb = q->xlb;		p->xlbf = q->xlbf;	}	if(p->xub<q->xub) {		p->xub = q->xub;		p->xubf = q->xubf;	}}void axes(void){	int i;	int mark[50];	int xn, yn;	if(gridf==0)		return;	line(xd.xbot,yd.xbot,xd.xtop,yd.xbot);	vec(xd.xtop,yd.xtop);	vec(xd.xbot,yd.xtop);	vec(xd.xbot,yd.xbot);	xn = setmark(mark,&xd);	for(i=0; i<xn; i++) {		if(gridf==2)			line(mark[i],yd.xbot,mark[i],yd.xtop);		if(gridf==1) {			line(mark[i],yd.xbot,mark[i],yd.xbot+tick);			line(mark[i],yd.xtop-tick,mark[i],yd.xtop);		}	}	yn = setmark(mark,&yd);	for(i=0; i<yn; i++) {		if(gridf==2)			line(xd.xbot,mark[i],xd.xtop,mark[i]);		if(gridf==1) {			line(xd.xbot,mark[i],xd.xbot+tick,mark[i]);			line(xd.xtop-tick,mark[i],xd.xtop,mark[i]);		}	}}intsetmark(int *xmark, struct xy *p){	int xn = 0;	float x,xl,xu;	float q;	if(p->xf==log10&&!p->xqf) {		for(x=p->xquant; x<p->xub; x*=10) {			submark(xmark,&xn,x,p);			if(p->xub/p->xlb<=100) {				submark(xmark,&xn,2*x,p);				submark(xmark,&xn,5*x,p);			}		}	} else {		xn = 0;		q = p->xquant;		if(q>0) {			xl = modceil(p->xlb+q/6,q);			xu = modfloor(p->xub-q/6,q)+q/2;		} else {			xl = modceil(p->xub-q/6,q);			xu = modfloor(p->xlb+q/6,q)-q/2;		}		for(x=xl; x<=xu; x+=fabs(p->xquant))			xmark[xn++] = (*p->xf)(x)*p->xa + p->xb;	}	return(xn);}void submark(int *xmark, int *pxn, float x, struct xy *p){	if(1.001*p->xlb < x && .999*p->xub > x)		xmark[(*pxn)++] = log10(x)*p->xa + p->xb;}void plot(void){	int ix,iy;	int i,j;	int conn;	for(j=0;j<ovlay;j++) {		switch(mode) {		case -1:			pen(modes[j%(sizeof modes/sizeof *modes-1)+1]);			break;		case 0:			break;		default:			pen(modes[mode]);		}		color(palette[pencolor].name);		conn = 0;		for(i=j; i<n; i+=ovlay) {			if(!conv(xx[i].xv,&xd,&ix) ||			   !conv(xx[i].yv,&yd,&iy)) {				conn = 0;				continue;			}			if(mode!=0) {				if(conn != 0)					vec(ix,iy);				else					move(ix,iy);				conn = 1;			}			conn &= symbol(ix,iy,xx[i].lblptr);		}		pencolor = palette[pencolor].next;	}	pen(modes[1]);}intconv(float xv, struct xy *p, int *ip){	long ix;	ix = p->xa*(*p->xf)(xv*p->xmult) + p->xb;	if(ix<p->xbot || ix>p->xtop)		return(0);	*ip = ix;	return(1);}intgetfloat(float *p){	int i;	i = scanf("%f",p);	return(i==1);}intgetstring(void){	int i;	char junk[20];	i = scanf("%1s",labbuf);	if(i==-1)		return(-1);	switch(*labbuf) {	default:		if(!isdigit(*labbuf)) {			ungetc(*labbuf,stdin);			i = scanf("%s",labbuf);			break;		}	case '.':	case '+':	case '-':		ungetc(*labbuf,stdin);		return(0);	case '"':		i = scanf("%[^\"\n]",labbuf);		scanf("%[\"]",junk);		break;	}	if(i==-1)		return(-1);	return(strlen(labbuf));}intsymbol(int ix, int iy, int k){	if(symbf==0&&k<0) {		if(mode==0)			point(ix,iy);		return(1);	} 	else {		move(ix,iy);		text(k>=0?labels+k:plotsymb);		move(ix,iy);		return(!brkf|k<0);	}}void title(void){	char buf[BSIZ+100];	buf[0] = ' ';	buf[1] = ' ';	buf[2] = ' ';	strcpy(buf+3,titlebuf);	if(erasf&&gridf) {		axlab('x',&xd,buf);		strcat(buf,",");		axlab('y',&yd,buf);	}	move(xd.xbot,yd.xbot-60);	text(buf);}void axlab(char c, struct xy *p, char *b){	char *dir;	dir = p->xlb<p->xub? "<=": ">=";	sprintf(b+strlen(b), " %g %s %c%s %s %g", p->xlb/p->xmult,		dir, c, p->xf==log10?" (log)":"", dir, p->xub/p->xmult);}void badarg(void){	fprintf(stderr,"graph: error in arguments\n");	closepl();	exits("bad arg");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -