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

📄 join.c

📁 操作系统源代码
💻 C
字号:
/* join - relation data base operator	Author:  Saeko Hirabayashi *//* Written by Saeko Hirabayashi, 1989. * 1992-01-28 Modified by Kouichi Hirabayashi to add some POSIX1003.2 options. * * This a free program. */#include <string.h>#include <stdio.h>#define MAXFLD	200		/* maximum # of fields to accept */_PROTOTYPE(void main, (int argc, char **argv));_PROTOTYPE(void error, (char *s, char *t));_PROTOTYPE(void usage, (void));_PROTOTYPE(void match, (void));_PROTOTYPE(void f1_only, (void));_PROTOTYPE(void f2_only, (void));_PROTOTYPE(void output, (int flag));_PROTOTYPE(void outfld, (int file));_PROTOTYPE(void outputf, (int flag));_PROTOTYPE(int compare, (void));_PROTOTYPE(int get1, (void));_PROTOTYPE(int get2, (int back));_PROTOTYPE(int getrec, (int file));_PROTOTYPE(int split, (int file));_PROTOTYPE(int atoi, (char *str));_PROTOTYPE(int exit, (int val));_PROTOTYPE(FILE * efopen, (char *file, char *mode));_PROTOTYPE(void (*outfun), (int file));	/* output func: output() or outputf()*/#define F1	1#define F2	2#define SEP	(sep ? sep : ' ')FILE *fp[2];			/* file pointer for file1 and file2 */long head;			/* head of the current (same)key group of the				 * file2 */char buf[2][BUFSIZ];		/* input buffer for file1 and file2 */char *fld[2][MAXFLD];		/* field vector for file1 and file2 */int nfld[2];			/* # of fields for file1 and file2 */int kpos[2];			/* key field position for file1 and file2				 * (from 0) */char oldkey[BUFSIZ];		/* previous key of the file1 */struct {			/* output list by -o option */  int o_file;			/* file #: 0 or 1 */  int o_field;			/* field #: 0, 1, 2, .. */} olist[MAXFLD];int nout;			/* # of output filed */int aflag;			/* n for '-an': F1 or F2 or both */int vflag;			/* n for '-vn': F1 or F2 or both */char *es;			/* s for '-e s' */char sep;			/* c for -tc: filed separator */char *cmd;			/* name of this program */void main(argc, argv)int argc;char **argv;{  register char *s;  int c, i, j;  cmd = argv[0];  outfun = output;		/* default output form */  while (--argc > 0 && (*++argv)[0] == '-' && (*argv)[1]) {	/* "-" is a file name (stdin) */	s = argv[0] + 1;	if ((c = *s) == '-' && !s[1]) {		++argv;		--argc;		break;		/* -- */	}	if (*++s == '\0') {		s = *++argv;		--argc;	}	switch (c) {	    case 'a':		/* add unpairable line to output */		vflag = 0;		switch (*s) {		    case '1':	aflag |= F1;	break;		    case '2':	aflag |= F2;	break;		    default:	aflag |= (F1 | F2);	break;		}		break;	    case 'e':		/* replace empty field by es */		es = s;		break;	    case 'j':		/* key field (obsolute) */		c = *s++;		if (*s == '\0') {			s = *++argv;			--argc;		}	    case '1':		/* key field of file1 */	    case '2':		/* key field of file2 */		i = atoi(s) - 1;		switch (c) {		    case '1':	kpos[0] = i;	break;		    case '2':	kpos[1] = i;	break;	            default:	kpos[0] = kpos[1] = i;				break;		}		break;	    case 'o':		/* specify output format */		do {			i = j = 0;			sscanf(s, "%d.%d", &i, &j);			if (i < 1 || j < 1 || i > 2) usage();			olist[nout].o_file = i - 1;			olist[nout].o_field = j - 1;			nout++;			if ((s = strchr(s, ',')) != (char *) 0)				s++;			else {				s = *++argv;				--argc;			}		} while (argc > 2 && *s != '-');		++argc;		--argv;		/* compensation */		outfun = outputf;		break;	    case 't':		/* tab char */		sep = *s;		break;	    case 'v':		/* output unpairable line only */		aflag = 0;		switch (*s) {		    case '1':	vflag |= F1;	break;		    case '2':	vflag |= F2;	break;		    default:	vflag |= (F1 | F2);	break;		}		break;	    default:	usage();	}  }  if (argc != 2) usage();  fp[0] = strcmp(argv[0], "-") ? efopen(argv[0], "r") : stdin;  fp[1] = efopen(argv[1], "r");  nfld[0] = get1();		/* read file1 */  nfld[1] = get2(0);		/* read file2 */  while (nfld[0] || nfld[1]) {	if ((i = compare()) == 0)		match();	else if (i < 0)		f1_only();	else		f2_only();  }  fflush(stdout);  exit(0);}void usage(){  fprintf(stderr,    "Usage: %s [-an|-vn] [-e str] [-o list] [-tc] [-1 f] [-2 f] file1 file2\n",    cmd);  exit(1);}int compare(){				/* compare key field */  register int r;  if (nfld[1] == 0)		/* file2 EOF */	r = -1;  else if (nfld[0] == 0)	/* file1 EOF */	r = 1;  else {	if (nfld[0] <= kpos[0])		error("missing key field in file1", (char *) 0);	if (nfld[1] <= kpos[1])		error("missing key field in file2", (char *) 0);	r = strcmp(fld[0][kpos[0]], fld[1][kpos[1]]);  }  return r;}void match(){  long p;  if (!vflag) (*outfun) (F1 | F2);  p = ftell(fp[1]);  nfld[1] = get2(0);		/* check key order */  if (nfld[1] == 0 || strcmp(fld[0][kpos[0]], fld[1][kpos[1]])) {	nfld[0] = get1();	if (strcmp(fld[0][kpos[0]], oldkey) == 0) {		fseek(fp[1], head, 0);	/* re-do from head */		nfld[1] = get2(1);	/* don't check key order */	} else		head = p;	/* mark here */  }}void f1_only(){  if ((aflag & F1) || (vflag & F1)) (*outfun) (F1);  nfld[0] = get1();}void f2_only(){  if ((aflag & F2) || (vflag & F2)) (*outfun) (F2);  head = ftell(fp[1]);		/* mark */  nfld[1] = get2(0);		/* check key order */}void output(f){				/* default output form */  if (f & F1)	fputs(fld[0][kpos[0]], stdout);  else	fputs(fld[1][kpos[1]], stdout);  if (f & F1) outfld(0);  if (f & F2) outfld(1);  fputc('\n', stdout);}void outfld(file){				/* output all fields except key_field */  register int i;  int k, n;  k = kpos[file];  n = nfld[file];  for (i = 0; i < n; i++)	if (i != k) {		fputc(SEP, stdout);		fputs(fld[file][i], stdout);	}}void outputf(f){				/* output by '-o list' */  int i, j, k;  register char *s;  for (i = k = 0; i < nout; i++) {	j = olist[i].o_file;	if ((f & (j + 1)) && (olist[i].o_field < nfld[j]))		s = fld[j][olist[i].o_field];	else		s = es;	if (s) {		if (k++) fputc(SEP, stdout);		fputs(s, stdout);	}  }  fputc('\n', stdout);}int get1(){				/* read file1 */  int r;  static char oldkey1[BUFSIZ];  if (fld[0][kpos[0]]) {        strcpy(oldkey, fld[0][kpos[0]]);  /* save previous key for control */  }  r = getrec(0);  if (r) {        if (strcmp(oldkey1, fld[0][kpos[0]]) > 0)	      error("file1 is not sorted", (char *) 0);        strcpy(oldkey1, fld[0][kpos[0]]);  /* save prev key for sort check */  }  return r;}int get2(back){				/* read file2 */  static char oldkey2[BUFSIZ];  int r;  r = getrec(1);  if (r) {        if (!back && strcmp(oldkey2, fld[1][kpos[1]]) > 0)	      error("file2 is not sorted", (char *) 0);        strcpy(oldkey2, fld[1][kpos[1]]);  /* save prev key for sort check */  }  return r;}int getrec(file){				/* read one line to split it */  if (fgets(buf[file], BUFSIZ, fp[file]) == (char *) 0)	*buf[file] = '\0';  else if (*buf[file] == '\n' || *buf[file] == '\r')	error("null line in file%s", file ? "1" : "0");  return split(file);}int split(file){				/* setup fields */  register int n;  register char *s, *t;  for (n = 0, s = buf[file]; *s && *s != '\n' && *s != '\r';) {	if (sep) {		for (t = s; *s && *s != sep && *s != '\n' && *s != '\r'; s++);	} else {		while (*s == ' ' || *s == '\t')			s++;	/* skip leading white space */		for (t = s; *s && *s != ' ' && *s != '\t'		     && *s != '\n' && *s != '\r'; s++);		/* We will treat trailing white space as NULL field */	}	if (*s) *s++ = '\0';	fld[file][n++] = t;	if (n == MAXFLD) error("too many filed in file%s", file ? "1" : "0");  }  fld[file][n] = (char *) 0;  return n;}FILE *efopen(file, mode)char *file, *mode;{  FILE *fp;  if ((fp = fopen(file, mode)) == (FILE *) 0) error("can't open %s", file);  return fp;}void error(s, t)char *s, *t;{  fprintf(stderr, "%s: ", cmd);  fprintf(stderr, s, t);  fprintf(stderr, "\n");  exit(1);}

⌨️ 快捷键说明

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