Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Как избавиться от повторения кода


Автор: Voldemar2004 17.11.2006, 23:36
У меня такой вопрос: как избавиться от повторения одного и того же кода. Например у меня есть функция сортировки прямым выбором:
Код
Straight_Sort(int key, int count, int *array)
{
                        if( key > 0 )
                        {

                                /* n-1 раз ищем наименьший элемент: */
                                for(unsigned int i = 0; i < count-1; ++i)
                                {
                                /* принимаем за наименьший 1-ый из рассматриваемых элементов: */
                                unsigned int imin = i;

                                /* поиск номера минимального элемента из неупорядоченных. */
                                for(unsigned int j = i + 1; j < count; ++j)

                                        /* если нашли меньший элемент, запоминаем его номер: */
                                        if (array[j] < array[imin]) imin = j;

                                        float buffer = array[i]; /* обмен элементов */
                                        array[i] = array[imin];  /* с номерами */
                                        array[imin] = buffer;    /* i и imin */

                                }

                        }

                        else
                        {
                                /* n-1 раз ищем наибольший элемент: */
                                for(unsigned int i = 0; i < count-1; ++i)
                                {
                                /* принимаем за наибольший 1-ый из рассматриваемых элементов: */
                                unsigned int imax = i;

                                /* поиск номера наибольшего элемента из неупорядоченных. */
                                for(unsigned int j = i + 1; j < count; ++j)

                                        /* если нашли наибольший элемент, запоминаем его номер: */
                                        if (array[j] > array[imax]) imax = j;

                                        float buffer = array[i]; /* обмен элементов */
                                        array[i] = array[imax];  /* с номерами */
                                        array[imax] = buffer;    /* i и imax */

                                }

                        };

}


Как бы покрасивее избавиться от повторения кода, ведь код
Код
float buffer = array[i]; /* обмен элементов */
array[i] = array[imax];  /* с номерами */
array[imax] = buffer;    /* i и imax */
повторяется 2 раза.

В книге нашел:
Цитата
Класс, в котором определена операция вызова функции, называется функциональным.
Код
class if_greater{
public:
int operator () (int a, int b) const {
return a > b;
}
};
Можно этот класс как-то использовать в данном случае?

В результате:
Код

if_greater x;
cout << x(1, 5) << endl;
cout << if_greater()(5, 1) << endl;

Автор: vinter 17.11.2006, 23:41
ИМХО самое простое, засунь в inline ф-ию..

Автор: Voldemar2004 17.11.2006, 23:47
Цитата(vinter @  18.11.2006,  00:41 Найти цитируемый пост)
inline
inline, как много в этом звуке... Но тогда придется создавать inline ф-цию, чтобы вставлять ее инлайн-методом в тело другой (сортировки) функции. И по-моему я читал, что компилятор сам определяет, определить ф-цию, как inline или нет.

Автор: Kuvaldis 17.11.2006, 23:53
Voldemar2004, 
Код

#include <algorithm>
....
swap(array[i] , array[imax]); 

Автор: sergejzr 18.11.2006, 00:11
А почему в простую функцию типа:


Код

void exchange(float * array, int idx1, int idx2)
{
  float buffer = array[idx1]; /* обмен элементов */
  array[idx1] = array[idx2];  /* с номерами */
  array[idx2] = buffer;    /* i и imax */
}   
void exchange(float &f1, ifloat &f2)
{
  float buffer = f1; /* обмен элементов */
  f1 = f2;  /* с номерами */
  f2 = buffer;    /* i и imax */
}   


Вообще конечно можно шаблоном для разных типов это сделать. 
Код

template <class T>
void exchange(T* array, int idx1, int idx2)
{
  T buffer = array[idx1]; /* обмен элементов */
  array[idx1] = array[idx2];  /* с номерами */
  array[idx2] = buffer;    /* i и imax */
}

template <class T>
void exchange( T &f1,T &f2)
{
  T buffer = f1; /* обмен элементов */
  f1 = f2;  /* с номерами */
  f2 = buffer;    /* i и imax */
}


Но я бы например  макрос написал (Хоть знаю, что С++ шники макросы не любят, но ИМХО тут подходит smile )

Код

#define exchange(array,a,b) {int *ai=(int*)(&array[a]); int *bi=(int*)(&array[b]); (*ai)^=(*bi);(*bi)^=(*ai);(*ai)^=(*bi);}
//вызов: 
exchange(buffer,i,imax);

Ты не смотри, что буков много. Компилер это соптимирует практически в 3 строкиsmile

Добавлено @ 00:15 
O, Kuvaldis дело говорит, нефиг велик изобретать  smile smile))

Автор: Kuvaldis 18.11.2006, 00:26
sergejzr, 
1. Не хочу тебя огорчать, но зачем писать свое, если есть стандартная шаблонная функция swap() из STL, проверенная и быстро работающая.

2.  
Код

#define exchange(array,a,b) {int *ai=(int*)(&array[a]); int *bi=(int*)(&array[b]); (*ai)^=(*bi);(*bi)^=(*ai);(*ai)^=(*bi);}

Есть хороший способ писать макросы красиво, в несколько строчек - использование символа \ (я когда узнал, был очень рад)
Код

#define exchange(array,a,b) \
                 {int *ai=(int*)(&array[a]); \
                  int *bi=(int*)(&array[b]); \
                  (*ai)^=(*bi);\
                  (*bi)^=(*ai);\
                  (*ai)^=(*bi);}


Но макросы использовать - это ОЧЕНЬ плохо
1. Их нельзя отлаживать
2. В них могут быть неявные присвоения
3. Не экономно расходуется память 
4. НЕТ ПРОВЕРКИ на соответствие типов.
5. Не очень удобно писать

Автор: sergejzr 18.11.2006, 00:45

Цитата(Kuvaldis @  17.11.2006,  23:26 Найти цитируемый пост)
1. Не хочу тебя огорчать, но зачем писать свое, если есть стандартная шаблонная функция swap() из STL, проверенная и быстро работающая.

Я же уже отписался насчёт неё.   smile (Насчёт "быстро" я бы не стал утверждать. Кто её знает, как она реализована  smile  (шутка))

Цитата(Kuvaldis @  17.11.2006,  23:26 Найти цитируемый пост)
Есть хороший способ писать макросы красиво, в несколько строчек - использование символа \ (я когда узнал, был очень рад)

Я знаю, но тогда как раз он становится похож на код. Это как раз может запутать. Но это уже по вкусу.

На мелочи вроде этого - макросы не страшны. Нельзя сказать в общем виде, что плохо, а что хорошо. Это как GОТО.
Все 5 пунктов в данном случае не важны. А http://forum.vingrad.ru/index.php?showtopic=119588&view=findpost&p=911039, которые без макроса вообще не сделать никак.

PS:
В данном случае это просто способ не использовать вызовы функции


Автор: Kuvaldis 18.11.2006, 00:56
sergejzr, 
Цитата

Все 5 пунктов в данном случае не важны. А есть вещи, которые без макроса вообще не сделать никак.

К сожалению, это не тот случай, имхо.
Насчет макросов  - еще неплохая штука- макрос assert.
 
Цитата

В данном случае это просто способ не использовать вызовы функции

Лучше уж inline функцию, из-за 5 пунктов...
Т.е. если альтернативы макросам нет, то придется использовать, иначе...

Автор: Dov 18.11.2006, 01:08
Цитата(Voldemar2004 @  17.11.2006,  23:36 Найти цитируемый пост)
 как избавиться от повторения одного и того же кода.

Voldemar2004, бери и не мучайся
Код
void Straight_Sort(int key, int count, int *array)
{
    for(int i = 0; i < count-1; ++i)                       
    {            
        int minmax = i;                                 
        for(int j = i + 1; j < count; ++j)            
            if((array[key ? j : minmax] < array[key ? minmax : j]))
                minmax = j;
            
        int buffer    = array[i];                               
        array[i]      = array[minmax];                     
        array[minmax] = buffer;                           
    }    
}



Автор: Voldemar2004 20.11.2006, 19:53
Проблема решена.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)