C: пример дублирования кода

Я пишу функции, которые принимают контрольную сумму двух разных вещей: во-первых, файла; и два, архивная запись а-ля библиотечной библиотеки BSD. Я позаимствовал код контрольной суммы из coreutils GNU.

Мой код для выполнения контрольной суммы файла читается из его источника следующим образом:

unsigned char buf[BUFLEN];
size_t bytes_read;
FILE *fp;
...
while ((bytes_read = fread (buf, 1, BUFLEN, fp)) > 0) { ... }

В моем коде для чтения из архивной записи соответствующий код выглядит так

struct archive *ar;
unsigned char buf[BUFLEN];
ssize_t bytes_read;
...
while ((bytes_read = archive_read_data(ar, buf, sizeof(buf))) > 0) { ... }

В нынешнем виде у меня должны быть две разные функции, хотя большая часть кода одинакова. Я не совсем понимаю, как это сделать, передав указатель на функцию, поскольку fread и archive_read_data даже не имеют одинакового количества аргументов. (Думаю, я мог бы начать с чтения (2) вместо fread (3), но я не уверен, что это продуктивный способ продолжить.)

Есть ли хороший способ избежать дублирования кода здесь? Помимо попытки сделать это с помощью указателей на функции, я мог бы сделать это, поместив идентичные фрагменты кода в отдельные файлы, а затем #including' их, но это выглядит уродливо.

В этом конкретном примере код для функций не такой длинный, так что простое дублирование кода не так уж и сложно. Мне просто интересно, существует ли элегантное решение.


person user1071847    schedule 10.04.2012    source источник


Ответы (3)


Вы можете создавать свои собственные функции-оболочки для fread() и archive_read_data(), которые имеют идентичные прототипы. Каждая из этих оболочек будет содержать только одну строку кода для вызова базовой функции read(), переставляя параметры по мере необходимости.

Затем используйте указатель функции, чтобы различать две ваши оболочки в зависимости от контекста.

person Graham Borland    schedule 10.04.2012

Если код, анализирующий контрольную сумму, один и тот же, вы можете превратить его в функцию — это часть внутри фигурной скобки. На мой взгляд, не так уж и плохо иметь два отдельных цикла, если они вызывают одну и ту же функцию. Их можно рассматривать как тонкую обертку.

person Israel Unterman    schedule 10.04.2012

Обе функции действительно нуждаются только в 3 аргументах:

  • указатель на источник данных
  • указатель на буфер данных
  • количество байтов для чтения

Вы можете написать функцию-оболочку для fread, чтобы дать ей ту же подпись, что и archive_read_data (или наоборот):

ssize_t my_fread(FILE *fp, char *buf, int len) {
  return fread(buf, 1, len, fp);
}
person Adam Liss    schedule 10.04.2012