272 lines · 4.0 KB · C
RawDownload
/* * Given a file and a list of field names, print the field values. * N.B. A record is a line of data. A field is a string delimited by a space, \t or \n. * * The file format is: * # descr of N: field0name field1name ... fieldNname * rec0field0val rec0field1val ... rec0fieldNval * ... * recMfield0val recMfield1val ... recMfieldNval */ #include <stdio.h>#include <stdint.h>#include <stdlib.h>#include <string.h>#include <stdarg.h>#include <err.h> enum {	Maxname = 256,}; typedef struct {	FILE		*fp;				/* Pointer to FILE */	uint32_t	recoff;				/* Offset of first record in fp */	uint32_t	nrecs;				/* Number of records in fp */	uint32_t	nfields;			/* Number of fields per record */	char		**fields;			/* Table of the fields' names */} Data;  uint32_tcountfields(FILE *fp){	uint32_t nf; 	nf = 0;	if(fseek(fp, 0, SEEK_SET) != 0)		return -1; 	for(;;){		switch(fgetc(fp)){		case ' ':			nf++;			break;		case '\n':		case EOF:			return nf+1;	/* fields = spaces+1 */		default:			break;		}	}} intreadword(FILE *fp, char *buf, int nbuf){	int c, i; 	for(i = 0; i < nbuf; i++){		c = fgetc(fp);		if(c == ' ' || c == '\n' || c == EOF)			break;		else			buf[i] = c;	}	buf[i] = '\0';	return i;} intfillfields(Data *dp){	uint32_t nf, i, j;	char **tbl; 	fscanf(dp->fp, "# descr of %u: ", &nf); 	tbl = malloc(nf*sizeof(char*));	if(tbl == NULL)		return 0; 	for(i = 0; i < nf; i++){		tbl[i] = malloc(Maxname);		if(tbl[i] == NULL){			for(j = i-1; j >= 0; j--)				free(tbl[j]);			free(tbl);			return 0;		}		readword(dp->fp, tbl[i], Maxname);	}		dp->recoff = ftell(dp->fp);	dp->fields = tbl;	dp->nfields = nf;	return 1;} voidcountrecs(Data *dp){	dp->nrecs = 0;	fseek(dp->fp, dp->recoff, SEEK_SET); 	for(;;){		switch(fgetc(dp->fp)){		case '\n':			dp->nrecs++;			break;		case EOF:			fseek(dp->fp, dp->recoff, SEEK_SET);			return;		default:			break;		}	}} Data*newdata(char *path){	Data *dp;	FILE *fp; 	fp = fopen(path, "r");	if(fp == NULL)		return NULL; 	if(fseek(fp, 0, SEEK_SET) != 0)		return NULL; 	dp = malloc(sizeof(Data));	if(dp == NULL)		return NULL;	dp->fp = fp; 	if(!fillfields(dp)){		free(dp);		return NULL;	}	countrecs(dp);	return dp;} intjumptorec(Data *dp, uint32_t rec){	uint32_t i; 	if(rec > dp->nrecs)		rec = dp->nrecs; 	for(i = 0; i < rec;){		switch(fgetc(dp->fp)){		case '\n':			i++;			break;		case EOF:			return 0;		default:			break;		}	}	return 1;} intjumptofield(Data *dp, uint32_t fld){	uint32_t i;		if(fld > dp->nfields)		fld = dp->nfields; 	for(i = 0; i < fld;){		switch(fgetc(dp->fp)){		case ' ':			i++;			break;		case EOF:			return 0;		default:			break;		}	}	return 1;} intjumpto(Data *dp, uint32_t rec, uint32_t fld){	fseek(dp->fp, dp->recoff, SEEK_SET);	if(!jumptorec(dp, rec))		return 0;	if(!jumptofield(dp, fld))		return 0;	return 1;} intfindfield(Data *dp, char *s){	uint32_t i; 	for(i = 0; i < dp->nfields; i++){		if(strncasecmp(dp->fields[i], s, Maxname) == 0)			return i;	}	return -1;} voidprintfields(Data *dp, uint32_t *fld, uint32_t nfld){	uint32_t i, j;	char buf[Maxname]; 	for(i = 0; i < dp->nrecs; i++){		for(j = 0; j < nfld; j++){			if(!jumpto(dp, i, fld[j]))				err(1, "premature eof 1");			readword(dp->fp, buf, sizeof(buf));			printf("%s ", buf);		}		puts("");	}}	voidusage(void){	fprintf(stderr, "usage: ExN file fields\n");	exit(1);} intmain(int argc, char *argv[]){	uint32_t i, *fld, *p, j, nf;	Data *dp; 	if(argc < 3 || (argv[1][0] == '-' && argv[1][1] == 'h'))		usage(); 	dp = newdata(argv[1]);	if(dp == NULL)		err(1, "could not allocate Data"); 	fld = malloc((argc-2)*sizeof(uint32_t));	if(fld == NULL)		err(1, "out of memory for fld");	memset(fld, -1, (argc-2)*sizeof(uint32_t)); 	p = fld;	nf = 0;	for(i = 2; i < argc; i++){		j = findfield(dp, argv[i]);		if(j == -1){			fprintf(stderr, "%s is not a field of %s\n", argv[i], argv[1]);			continue;		}		*p = j;		p++;		nf++;	} 	printfields(dp, fld, nf);	return 0;} 	

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t