Telefang
Telefang

Reputation: 133

Comparing two txt files in c

I'm trying to compare 2 text files and print the first line where they differ but I'm using a buffer of 500 in the fgets() command and I think I'm wasting space. How can I make the same program if I don't know the length of the line?

Here is my code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char const *argv[])
{
    FILE *fp1, *fp2;

    int nLine = 1;
    char l1[500], l2[500];

    system("clear");

    if (argc < 3)
    {
        printf("Usage: %s <file1.txt> <file2.txt>\n",argv[0]);
        exit(1);
    }

    if ((fp1 = fopen(argv[1],"r")) == NULL){
        printf("Can't open file: %s\n", argv[1]);
        exit(1);
    }

    if ((fp2 = fopen(argv[2],"r")) == NULL){
        printf("Can't open file: %s\n", argv[2]);
        exit(1);
    }

    fgets(l1,500,fp1);
    fgets(l2,500,fp2);

    while ((l1 != 0) && (l2 != 0)){
        if(strcmp(l1,l2) != 0){
            printf("Line number: %d\n", nLine);
            printf("%s", l1);
            printf("%s\n", l2);
            exit(1);
        } else {
            fgets(l1,500,fp1);
            fgets(l2,500,fp2);
            nLine++;    
        }   
    }

    return 0;
}

Upvotes: 1

Views: 2179

Answers (1)

chux
chux

Reputation: 153447

If you do not want to "waste space", remember that the data are in file memory. Read 1 character at time. When you find a difference, just seek to that location of the previous line feed and report the following lines.

long index = 0;
long index_lf = 0;
int c1,c2;

// read until a difference or done
while ((c1 = fgetc(fp1)) == (c2 = fgetc(fp2)) && (c1 != EOF)) {
  index++;
  if (c1 == '\n') index_lf = index;
}
if (c1 == c2) {
  puts("same");
} else {
  puts("differ");
  fseek(fp1, index_lf, SEEK_SET);
  fseek(fp2, index_lf, SEEK_SET);
  // read and print each file until a following \n or EOF occurs.
  // TBD code for OP
}

[Edit] Some improvements to cope with various issues: mis-match on last byte, files opened in different modes, error handling, etc.

long offset1 = ftell(fp1);;
long offset2 = ftell(fp2);;
int c1,c2;

// read until a difference or done
while ((c1 = fgetc(fp1)) == (c2 = fgetc(fp2)) && (c1 != EOF)) {
  if (c1 == '\n') {
    offset1 = ftell(fp1);
    offset2 = ftell(fp2);
  }
}

if (offset1 == -1 || offset2 == -1 || ferror(fp1) || ferror(fp2)) {
  puts("problem");
} else if (c1 == c2) {
  puts("same");
} else {
  puts("differ");
  fseek(fp1, offset1, SEEK_SET);
  fseek(fp2, offset2, SEEK_SET);
  // read and print each file until a following \n or EOF occurs.
  // TBD code for OP
}

Upvotes: 3

Related Questions