Fread читает двойной из файла - PullRequest
0 голосов
/ 26 мая 2019

Я новичок в программировании на C и пытаюсь сравнить блоки по 1024 байта (сейчас я тестирую с 10) из 2 текстовых файлов и проверить, сколько из этих блоков идентично.

Я читаю блоки с помощью fread и сравниваю их с помощью strcmp, но fread читает дважды с первого файла, даже если я читаю одинаково с обоих.Так что это моя функция сравнения:

void compareFiles(FILE *fp1, FILE *fp2)
{
char fp1_content[10]; //should be 1024
char fp2_content[10]; //should be 1024

fread(fp1_content, 10, 1, fp1); //should be 1024
fread(fp2_content, 10, 1, fp2); //should be 1024

printf("content of 81.txt %s \n", fp1_content);
printf("content of 82.txt %s \n", fp2_content);

char ch1 = getc(fp1);
char ch2 = getc(fp2);
int eqBlocks = 0;

while (ch1 != EOF && ch2 != EOF)
{
    if (strcmp(fp1_content, fp2_content) == 0) {
        eqBlocks++;
    }

    ch1 = getc(fp1);
    ch2 = getc(fp2);

    fread(fp1_content, 10, 1, fp1);
    fread(fp2_content, 10, 1, fp2);
}
printf("Nb of identical blocks: %d\n", eqBlocks);
}

Здесь возникает проблема: у меня есть текст lorem ipsum, один и тот же текст в обоих файлах.Но первые два printfs выводят:

content of 81.txt Lorem ipsuLorem ipsu
content of 82.txt Lorem ipsu

Почему первый удваивается?Как мне это исправить?

1 Ответ

1 голос
/ 27 мая 2019

Код OP требует нескольких исправлений.

Возвращаемое значение

Такие функции, как fread(), возвращают полезную информацию.Используй их.В этом случае он говорит, сколько было прочитано. @ Флюгер

"% s" ожидает строку указатель

printf("content of 81.txt %s \n", fp1_content); ожидает fp1_content является строка .В C string всегда имеет нулевой символ , иначе это не строка.Чтобы напечатать текст, который может не иметь '\0', используйте "%.*s", который принимает аргумент для ограничения длины печати."%s" с нестроковым значением неопределенное поведение .Неожиданные вещи могут случиться. @ Tom Karzes

Сравните ненулевые строки с memcmp()

Ненужный код

char ch1 = getc(fp1); не нужно определять конец, используйте возвращаемое значение fread(). @ Жан-Франсуа Фабр В сторону: используйте int ch1, чтобы отличить 257 различных возвращаемых значений от fgets().

Избегайте обнаженных магических чисел

Вместо того, чтобы засорять код 10 здесь и там, используйте именованную константу.

Думайте масштабно

Файлы могут быть больше, чем INT_MAX блоков.Предложить long long eqBlocks.

#include <limits.h>
#define COMPAREFILES_N 10
#if COMPAREFILES_N > INT_MAX
#error Use smaller block
#endif

void compareFiles(FILE *fp1, FILE *fp2) {
  char fp1_content[COMPAREFILES_N];
  char fp2_content[COMPAREFILES_N];
  long long eqBlocks = 0;

  for (;;) {
    size_t len1 = fread(fp1_content, COMPAREFILES_N, 1, fp1);
    size_t len2 = fread(fp2_content, COMPAREFILES_N, 1, fp2);
    if (len1 < 1 || len2 < 1) {
      break;  // failed to read a block in each file
    }
    if (memcmp(fp1_content, fp2_content, COMPAREFILES_N) == 0) {
      eqBlocks++;
      printf("Common content `%.*s`\n", COMPAREFILES_N, fp1_content);
    }
  }

  printf("Nb of identical blocks: %lld\n", eqBlocks);
}
...