Task: Text processing_2

C: #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

typedef struct { const char *s; int ln, bad; } rec_t;
int cmp_rec(const void *aa, const void *bb)
{
	const rec_t *a = aa, *b = bb;
	return a->s == b->s ? 0 : !a->s ? 1 : !b->s ? -1 : strncmp(a->s, b->s, 10);
}

int read_file(const char *fn)
{
	int fd = open(fn, O_RDONLY);
	if (fd == -1) return 0;

	struct stat s;
	fstat(fd, &s);

	char *txt = malloc(s.st_size);
	read(fd, txt, s.st_size);
	close(fd);

	int i, j, lines = 0, k, di, bad;
	for (i = lines = 0; i < s.st_size; i++)
		if (txt[i] == '\n') {
			txt[i] = '\0';
			lines++;
		}

	rec_t *rec = calloc(sizeof(rec_t), lines);
	const char *ptr, *end;
	rec[0].s = txt;
	rec[0].ln = 1;
	for (i = 0; i < lines; i++) {
		if (i + 1 < lines) {
			rec[i + 1].s = rec[i].s + strlen(rec[i].s) + 1;
			rec[i + 1].ln = i + 2;
		}
		if (sscanf(rec[i].s, "%4d-%2d-%2d", &di, &di, &di) != 3) {
			printf("bad line %d: %s\n", i, rec[i].s);
			rec[i].s = 0;
			continue;
		}
		ptr = rec[i].s + 10;

		for (j = k = 0; j < 25; j++) {
			if (!strtod(ptr, (char**)&end) && end == ptr) break;
			k++, ptr = end;
			if (!(di = strtol(ptr, (char**)&end, 10)) && end == ptr) break;
			k++, ptr = end;
			if (di < 1) rec[i].bad = 1;
		}

		if (k != 48) {
			printf("bad format at line %d: %s\n", i, rec[i].s);
			rec[i].s = 0;
		}
	}

	qsort(rec, lines, sizeof(rec_t), cmp_rec);
	for (i = 1, bad = rec[0].bad, j = 0; i < lines && rec[i].s; i++) {
		if (rec[i].bad) bad++;
		if (strncmp(rec[i].s, rec[j].s, 10)) {
			j = i;
		} else
			printf("dup line %d: %.10s\n", rec[i].ln, rec[i].s);
	}

	free(rec);
	free(txt);
	printf("\n%d out %d lines good\n", lines - bad, lines);
	return 0;
}

int main()
{
	read_file("readings.txt");
	return 0;
}










Fortran: Crunches a set of hourly data. Starts with a date, then 24 pairs of value,indicator for that day, on one line.
      INTEGER Y,M,D		
      INTEGER GOOD(24,2)	
      REAL*8     V(24,2)	
      CHARACTER*10 DATE(2)	
      INTEGER IT,TI		
      INTEGER NV		
      INTEGER I,NREC,HIC	
      LOGICAL INGOOD		
      INTEGER IN,MSG		
      CHARACTER*666 ACARD	
      IN = 10		
      MSG = 6		
      OPEN (IN,FILE="Readings1.txt", FORM="FORMATTED",	
     1 STATUS ="OLD",ACTION="READ")			
      NV = 0		
      NREC = 0		
      HIC = 0		
      DATE = "snargle"	
      IT = 2		
Chew into the file.
   10 READ (IN,11,END=100,ERR=666) L,ACARD(1:MIN(L,LEN(ACARD)))	
      NREC = NREC + 1		
   11 FORMAT (Q,A)		
      READ (ACARD,12,END=600,ERR=601) Y,M,D	
   12 FORMAT (I4,2(1X,I2))				
      TI = IT			
      IT = 3 - IT		
      DATE(IT) = ACARD(1:10)	
      READ (ACARD(11:L),*,END=600,ERR=601) (V(I,IT),GOOD(I,IT),I = 1,24)	
Comparisons. Should really convert the date to a daynumber, check it by reversion, and then check for + 1 day only.
   20 IF (DATE(IT).EQ.DATE(TI)) THEN	
        IF (ALL(V(:,IT)   .EQ.V(:,TI)) .AND.	
     1      ALL(GOOD(:,IT).EQ.GOOD(:,TI))) THEN	
          WRITE (MSG,21) NREC,DATE(IT),"same."	
   21     FORMAT ("Record",I8," Duplicate date field (",A,"), data ",A)	
         ELSE				
          WRITE (MSG,21) NREC,DATE(IT),"different
        END IF					
      END IF				
      IF (ALL(GOOD(:,IT).GT.0)) NV = NV + 1	
      GO TO 10		

Complaints. Should really distinguish between trouble in the date part and in the data part.
  600 WRITE (MSG,*) '"END" declared - insufficient data?'	
      GO TO 602				
  601 WRITE (MSG,*) '"ERR" declared - improper number format?'	
  602 WRITE (MSG,603) NREC,L,ACARD(1:L)	
  603 FORMAT("Record",I8,", length ",I0," reads ",A)	
      HIC = HIC + 1			
      IF (HIC.LE.12) GO TO 10		
      STOP "Enough distaste."		
  666 WRITE (MSG,101) NREC,"format error
      GO TO 900				

Closedown.
  100 WRITE (MSG,101) NREC,"then end-of-file"	
  101 FORMAT ("Record",I8,": ",A)		
      WRITE (MSG,102) NV	
  102 FORMAT ("  with",I8," having all values good.")	
  900 CLOSE(IN)		
      END