--- title: "File Comparison" type: "article" slug: "file-comparison" url: "http://localhost/article/file-comparison/" markdown_url: "http://localhost/article/file-comparison.md" published_at: "2025-11-19T12:47:46+00:00" modified_at: "2026-06-21T23:22:42+00:00" featured_image: url: "http://localhost/wp-content/uploads/2022/04/20230809-041332.jpg" excerpt: "Fcomp_c is another C program from the C User's Journal disk #236 (Highly Portable Utilites). I only had to make a few minor changes to port it to the QL. The biggest change being uncommenting the #define NO_STRING_H. I have tried the program out with two short test files. Below is the two files and…" category: - name: "QL Hacker's Journal" slug: "ql-hackers-journal" taxonomy: "category" url: "http://localhost/category/periodicals/ql-hackers-journal/" post_tag: - name: "C (programming language)" slug: "c-programming-language" taxonomy: "post_tag" url: "http://localhost/tag/c-programming-language/" - name: "Full Text" slug: "fulltext" taxonomy: "post_tag" url: "http://localhost/tag/fulltext/" - name: "QL" slug: "ql" taxonomy: "post_tag" url: "http://localhost/tag/ql/" - name: "Type-in program" slug: "type-in-program" taxonomy: "post_tag" url: "http://localhost/tag/type-in-program/" model: - name: "Sinclair QL" slug: "sinclair-ql" taxonomy: "model" url: "http://localhost/model/sinclair-ql/" indiv: - name: "Tim Swenson" slug: "tim-swenson" taxonomy: "indiv" url: "http://localhost/indiv/tim-swenson/" publication_r: id: 33686 title: "QL Hacker’s Journal" type: "periodical" url: "http://localhost/periodical/ql-hackers-journal/" authors_r: - name: "Tim Swenson" slug: "tim-swenson" taxonomy: "indiv" url: "http://localhost/indiv/tim-swenson/" issue: "3" issues_articles: - id: 61539 title: "QL Hacker’s Journal 3" type: "issue" url: "http://localhost/issue/ql-hackers-journal-3/" pubdate: "April 1991" archive_link: true --- Fcomp_c is another C program from the C User’s Journal disk #236 (Highly Portable Utilites). I only had to make a few minor changes to port it to the QL. The biggest change being uncommenting the #define NO_STRING_H. I have tried the program out with two short test files. Below is the two files and the output from fcomp_c. ### File #1 ``` This is fcomp_c test file number 1. Line number 1 Line number 2 Line number 3 Line number 4 Line number 5 Line number 6 ``` ### File #2 ``` his is fcomp_c test file number . Line number 1 Line number 2 Line number 3 This line is added Line number 4 Line number 6 ``` ### Output From fcomp_c ``` hanged line 1 This is fcomp_c test file number 1. To: This is fcomp_c test file number 2. Inserted after line 3: Inserted after line 6: This line added Deleted line 8 Line number 5 ``` ### CUG236: Compare Text Files ``` /* HEADER: CUG236; TITLE: Compare Text Files; DATE: 05/17/1987; DESCRIPTION: "Best version of DIFF (file comparator) from Jan '86 issue of Software Practice and Experience."; VERSION: 1.1; KEYWORDS: File Comparator, File Compare, File Comparison, File Comparison Utility; FILENAME: FCOMP.C; SEE-ALSO: DIFF; COMPILERS: vanilla; AUTHORS: Chuck Allison; */ /* fcomp.c: file comparator that beats DIFF! */ #include /* * Portability Note: 8-bit systems often don't have header file string.h. * If your system doesn't have it, uncomment the following #define. */ #define NO_STRING_H /* * Portability Note: Back in K & R days, standard library function malloc() * was called alloc(). Some compilers (e.g. Eco-C under CP/M) haven't made * the name change. If yours is one of these compilers, uncomment the * following #define: */ /* #define malloc(p) alloc(p) */ /* * Portability Note: The AZTEC C compilers handle the binary/text file * dichotomy differently from most other compilers. Uncomment the following * pair of #defines if you are running AZTEC C: */ /* #define getc(f) agetc(f) #define putc(c,f) aputc(c,f) */ #ifdef NO_STRING_H int strcmp(), strlen(); #else #include #endif #define MAXLINES 1000 #define ORIGIN MAXLINES #define INSERT 1 #define DELETE 2 struct edit { struct edit *link; int op; int line1; int line2; }; char *A[MAXLINES], *B[MAXLINES]; void exit(); void main(argc,argv) int argc; char *argv[]; { int col, d, k, lower, m, max_d, n, row, upper; int last_d[2*MAXLINES+1]; struct edit *new, *script[2*MAXLINES+1]; char *malloc(); int atoi(), in_file(); void exceed(), fatal(), put_scr(); if (argc > 1 && argv[1][0] == '-') { max_d = atoi(&argv[1][1]); ++argv; --argc; } else max_d = 2*MAXLINES; if(argc != 3) fatal("fcomp requires two file names."); m = in_file(argv[1],A); n = in_file(argv[2],B); for (row=0 ; row upper) { puts("The files are identical."); exit(0); } for (d = 1 ; d <= max_d ; ++d) { for ( k = lower ; k <= upper ; k +=2) { new = (struct edit *) malloc(sizeof(struct edit)); if (new == NULL) exceed(d); if (k == ORIGIN-d || k != ORIGIN+d && last_d[k+1] >= last_d[k-1]) { row = last_d[k+1]+1; new->link = script[k+1]; new->op = DELETE; } else { row = last_d[k-1]; new->link = script[k-1]; new->op = INSERT; } new->line1 = row; new->line2 = col = row + k - ORIGIN; script[k] = new; while(row < m && col < n && strcmp(A[row],B[col]) == 0) { ++row; ++col; } last_d[k] = row; if (row == m && col == n) { put_scr(script[k]); exit(!0); } if (row == m) lower = k+2; if (col == n) upper = k-2; } --lower; ++upper; } exceed(d); } int in_file(filename,P) char *filename, *P[]; { char buf[100], *malloc(), *save, *b; FILE *fp; int lines = 0; void fatal(); if ((fp = fopen(filename,"r")) == NULL) { fprintf(stderr, "Cannot open file %s.\n",filename); exit(!0); } while(fgets(buf,100,fp) != NULL) { if (lines >= MAXLINES) fatal("File is too large for diff."); if ((save = malloc(strlen(buf)+1)) == NULL) fatal("Not enough room to save the files."); P[lines++] = save; for (b = buf ; *save++ = *b++ ; ) ; } fclose(fp); return(lines); } void put_scr(start) struct edit *start; { struct edit *ep, *behind, *ahead, *a, *b; int change; ahead = start; ep = NULL; while (ahead != NULL) { behind = ep; ep = ahead; ahead = ahead->link; ep->link = behind; } while( ep != NULL) { b = ep; if (ep->op == INSERT) printf("Inserted after line %d:\n",ep->line1); else { do { a = b; b = b->link; } while (b!=NULL && b->op == DELETE && b->line1 == a->line1+1); change = (b!=NULL && b->op == INSERT && b->line1 == a->line1); if (change) printf("\nChanged "); else printf("\nDeleted "); if (a == ep) printf("line %d\n",ep->line1); else printf("lines %d-%d:\n",ep->line1,a->line1); do { printf(" %s",A[ep->line1-1]); ep = ep->link; } while (ep != b); if (!change) continue; printf("To:\n"); } do { printf(" %s",B[ep->line2-1]); ep = ep->link; } while (ep != NULL && ep->op == INSERT && ep->line1 == b->line1); } } void fatal(msg) char *msg; { fprintf(stderr,"%s\n",msg); exit(!0); } void exceed(d) int d; { fprintf(stderr,"The files differ in at least %d lines. \n",d); exit(!0); } ```