Как обобщить функции в C - PullRequest
0 голосов
/ 06 мая 2020

Я пишу код, который выполняет базовый c анализ данных.

Собранные данные находятся в массиве структур. Он принимает приблизительную форму:

struct page {
  int width;
  int length;
  char name[50];
  // etc...
}

struct page pages[100];

Мне нужно написать код, который находит наименьшую ширину, наибольшую ширину, наименьшую длину, наибольшую длину и т. Д. c. Итак, я пишу код, который выглядит примерно так:

int smallestWidth(struct page pages[]){
unsigned int smallest = -1;
  (for loop){
    if (smallest > pages[i].width) smallest = pages[i].width;
  }
return smallest;
}

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

Но я вроде как новичок в C, поэтому я не уверен, как правильно подойти к этому. Как бы вы правильно записали это в C (если есть правильный способ), который минимизирует количество кода, который я копирую?

Ответы [ 2 ]

1 голос
/ 06 мая 2020

В языке C ++ есть переопределения и указатели на члены, которых нет в C. Таким образом, способ C заключался бы в использовании вспомогательных функций для извлечения правильных данных и их сравнения:

int getLength(struct page *page) {
    return page->length;
}
int getWidth(struct page *page) {
    return page->width;
}

int lesser(int a, int b) {
    return a<b;
}
int greater(int a, int b) {
    return a>b;
}

typedef int(*extractor)(struct page *p);
typedef int (*comparator)(int a, int b);

int process(struct page * p, int size, extractor ext, comparator cmp) {
    // code here the generic part
    ...
}

int lesserWidth = process(pages, 100, &getWidth, &lesser);
...

Но он включает много кода котельной пластины, поэтому он может быть интересен или не зависит от сложность дженери c часть ...

0 голосов
/ 06 мая 2020

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

struct page {
  int width;
  int length;
  // etc...
} pages[100] = {{1,2},{3,4},{5,6}};

int smallestX(struct page pages[], size_t offset)
{
    unsigned int smallest = -1, k;
    for (int i=0; i<3; i++){
        k= *((int *)((char *)(&pages[i])+offset));
        if (smallest > k) smallest = k;
  }
  return smallest;
}
void example(void)
{
    printf ("smallest width= %d\n", smallestX(pages, offsetof(struct page, width)));
    printf ("smallest length= %d\n", smallestX(pages, offsetof(struct page, length)));
}

Уточнение:

Он использует макрос offsetof для получения смещения члена от начала структуры. В функции теперь он принимает адрес i -го элемента массива, интерпретирует его как байтовый адрес, добавляет смещение (которое находится в байтах), интерпретирует это как указатель на int, разыменовывает эти int и использует его при сравнении.

Примечание: этот метод можно расширить для сравнения любого элемента, указав функцию сравнения в качестве параметра.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...