Не могу разобраться как работает функция (слабо знаю Си)

Тема в разделе "Arduino & Shields", создана пользователем AlexVS, 3 июн 2015.

  1. AlexVS

    AlexVS Гик

    Есть функция выполняющая роль медианного фильтра, совсем в синтаксисе запутался :(
    Может кто-нибудь разжует, хотя бы в общих чертах?
    Код (Text):
    #define NULL        0
    #define STOPPER  0 /* Smaller than any datum */
    #define MEDIAN_FILTER_SIZE 9
    int MedianFilter(int datum)
    {
    struct pair{
      struct pair *point; /* Pointers forming list linked in sorted order */
      int value; /* Values to sort */
    };
     
    /* Buffer of nwidth pairs */
    static struct pair buffer[MEDIAN_FILTER_SIZE] = {0};
    /* Pointer into circular buffer of data */
    static struct pair *datpoint = buffer;
    /* Chain stopper */
    static struct pair small = {NULL, STOPPER};
    /* Pointer to head (largest) of linked list.*/
    static struct pair big = {&small, 0};
    /* Pointer to successor of replaced data item */
    struct pair *successor;
    /* Pointer used to scan down the sorted list */
    struct pair *scan;
    /* Previous value of scan */
    struct pair *scanold;
    /* Pointer to median */
    struct pair *median;
    int i;
    if (datum == STOPPER){
      datum = STOPPER + 1; /* No stoppers allowed. */
    }
    if ( (++datpoint - buffer) >= MEDIAN_FILTER_SIZE){
      datpoint = buffer; /* Increment and wrap data in pointer.*/
    }
    datpoint->value = datum; /* Copy in new datum */
    successor = datpoint->point; /* Save pointer to old value's successor */
    median = &big; /* Median initially to first in chain */
    scanold = NULL; /* Scanold initially null. */
    scan = &big; /* Points to pointer to first (largest) datum in chain */

    /* Handle chain-out of first item in chain as special case */
    if (scan->point == datpoint){
      scan->point = successor;
    }
    scanold = scan; /* Save this pointer and */
    scan = scan->point ; /* step down chain */
    /* Loop through the chain, normal loop exit via break. */
    for (i = 0 ; i < MEDIAN_FILTER_SIZE; ++i){
      /* Handle odd-numbered item in chain */
      if (scan->point == datpoint){
        scan->point = successor; /* Chain out the old datum.*/
      }
      if (scan->value < datum){ /* If datum is larger than scanned value,*/
        datpoint->point = scanold->point; /* Chain it in here. */
        scanold->point = datpoint; /* Mark it chained in. */
        datum = STOPPER;
      };
      /* Step median pointer down chain after doing odd-numbered element */
      median = median->point; /* Step median pointer. */
     

      if (scan == &small){
        break; /* Break at end of chain */
      }
      scanold = scan; /* Save this pointer and */
      scan = scan->point; /* step down chain */
      /* Handle even-numbered item in chain. */
      if (scan->point == datpoint){
        scan->point = successor;
      }
      if (scan->value < datum){
        datpoint->point = scanold->point;
        scanold->point = datpoint;
        datum = STOPPER;
      }
      if (scan == &small){
        break;
      }
      scanold = scan;
      scan = scan->point;
    }

    return median->value;
    }
    Особенно непонятна конструкция типа: scan = scan->point; или scanold->point = datpoint;
     
  2. DrProg

    DrProg Вечный нерд

    Если не секрет, для чего может использоваться медианный фильтр в Ардуинке? Фантазии не хватает.
     
  3. AlexVS

    AlexVS Гик

    У меня окна выходят на солнечную сторону, поэтому датчик T & H сильно подвержен влиянию солнечного света. Я уже использую компенсацию на основе предыдущих показаний и значений с погодного сайта.
    Хочу теперь с фильтром поиграться, потому как солнце то вылезет, то скроется :)
     
    DrProg нравится это.
  4. DrProg

    DrProg Вечный нерд

    Ничего себе перфекционизм. ))
    Тут больше важен результат или процесс? Может быть проще вычислять среднее арифметическое из ряда замеров за заданное время, чем проводить корреляцию и подтягивать теорию вероятности? )
     
  5. AlexVS

    AlexVS Гик

    Да говорю же, среднее арифметическое - уже есть :)
    Лишний опыт и знания не помешают ;)
     
  6. DrProg

    DrProg Вечный нерд

    Да просто вопрос больше из области математики, чем программирования. :rolleyes:
     
  7. AlexVS

    AlexVS Гик

    Так что насчет разжевывания Сишных истин?
     
  8. DrProg

    DrProg Вечный нерд

    К сожалению, я пока тоже не настолько силен в С++ чтобы быстро разобраться с указателями и членами класса. Судя по всему производится вычисление фильтра максимально эффективным способом, а потому максимально сложным для понимания. Тут нужно терпение и время чтобы вникнуть. Оно хоть работает в таком виде?
     
  9. AlexVS

    AlexVS Гик

    В общем, Да, работает.
    Но что бы понять как, надо хоть элементарные Serial.print() вставить, а тут сплошные указатели - запутался сосвсем :(
     
  10. DrProg

    DrProg Вечный нерд

    Тоже хочу отжалеть немного времени и разобраться с указателями. Не уверен, что они пригодятся, но вдруг! Опять же знаний лишних не бывает. Давайте вместе разбираться или искать специалиста. )
     
    ИгорьК нравится это.
  11. Unixon

    Unixon Оракул Модератор

    Данные организованы в односвязный список. В поле point хранится указатель (адрес в памяти) следующего элемента в цепочке. У последнего элемента в цепочке point = NULL. Конструкция scan = scan->point; означает переход к следующему элементу в списке путем присваивания указателя на следующий элемент в списке указателю на текущий.
     
    Последнее редактирование: 3 июн 2015
    DrProg и AlexVS нравится это.
  12. AlexVS

    AlexVS Гик

    Как перебрать всю цепочку, что бы например вывести сохраненные значения?
     
  13. Unixon

    Unixon Оракул Модератор

    Код (Text):
    pair* p = datapoint;
    while (NULL!=p)
    {
    Serial.println(p->value);
    p = p->point;
    }
     
    AlexVS нравится это.
  14. DrProg

    DrProg Вечный нерд

    В чем преимущество перед одномерным массивом?
     
  15. Megakoteyka

    Megakoteyka Оракул Модератор

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

    https://ru.wikipedia.org/wiki/Связный_список
     
    DrProg нравится это.
  16. DrProg

    DrProg Вечный нерд

    Спасибо, интересная информация. Но, как вижу, у списков перед массивами есть и минуты тоже. То есть в каждом конкретном случае надо думать что будет использовать правильнее в зависимости от контекста.
     
  17. Megakoteyka

    Megakoteyka Оракул Модератор

    Списки хороши в тех случаях, когда количество данных заранее неизвестно либо требуется часто делать вставку/удаление.
    А думать всегда надо :)
     
  18. ИгорьК

    ИгорьК Гуру

    В данном случае, похоже, количество данных известно - девять штук. Перемещение по элементам массива с использованием указателей, ИМХО, не медленнее и не сложнее.
    Но за новую информацию спасибо.
     
  19. Megakoteyka

    Megakoteyka Оракул Модератор

    А доступ к произвольному элементу в случае с обычным массивом будет самый быстрый. Для списка же придется от головы перебирать указатели на следующий элемент требуемое число раз.
     
  20. ИгорьК

    ИгорьК Гуру

    Глядя на этот код, мне покаалось что он написан для самовыражения, а не для вычислений.
     
    DrProg нравится это.