The website "dmilvdv.narod.ru." is not registered with uCoz.
If you are absolutely sure your website must be here,
please contact our Support Team.
If you were searching for something on the Internet and ended up here, try again:

About uCoz web-service

Community

Legal information

10.7 Другое приложение — sort

10.7 Другое приложение — sort

Предыдущая  Содержание  Следующая V*D*V

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

Фильтр сортировки должен собрать все текстовые строки, отсортировать весь набор, и наконец записать их. Раздел 7.7 представил List на основе динамического кругового буфера, который мы можем использовать, чтобы собрать строки до того, как добавим метод сортировки. В разделе 2.5 мы реализовали простой класс String; если мы интегрируем его в нашу иерархию классов, то сможем использовать его для хранения всех строк в List.

Давайте начнём с главной программы, которая просто создаёт фильтр с его делегатом:

 

int main (int argc, char * argv []) {

    void * filter = new(Filter(), new(Sort(), 0));

 

    return mainLoop(filter, argv);

}

 

Поскольку мы можем подключить методы обратного вызова для любого класса, то можно создать делегата непосредственно в подклассе List:

 

% SortClass: ListClass Sort: List {

    char rflag;

%—

    void flags (_self, Object @ filter, char flag);

    int line (_self, const Object @ filter, const char * fnm, \

                                                char * buf);

    int quit (_self, const Object @ filter);

%}

 

Чтобы продемонстрировать обработку опции, мы распознаём -r как просьбу отсортировать в обратном порядке. Все другие флаги отбрасываются методом flags(), у которого есть тэг flag для respondsTo():

 

% flag: Sort flags {

%casts

    assert((flagM) flags == flags);

 

    if (flag == ’r’)

        self -> rflag = 1;

    else

        fprintf(stderr, "usage: %s [-r] [file...]\n",

                            progname(filter)),

    exit(1);

}

 

Имея String и List сбор линий тривиален:

 

% Sort line {

%casts

    assert((lineM) line == line);

 

    addLast(self, new(String(), buf));

    return 0;

}

 

Как только все строки собраны, обратный вызов quit заботится о сортировке и записи. Если есть хотя бы одна строка, мы позволяем новому виду sort() позаботиться о сортировке списка, а затем удаляем все строки поочередно и позволяем объекту String самому вывести себя на экран. Мы можем отсортировать в обратном порядке просто удаляя строки с конца списка:

 

% Sort quit {

%casts

    assert((quitM) quit == quit);

 

    if (count(self)) {

        sort(self);

        do

            puto(self -> rflag ? takeLast(self)

                            : takeFirst(self), stdout);

        while (count(self));

    }

    return 0;

}

 

Что можно сказать о sort()? ANSI-C для сортировки произвольных массивов на основе функции сравнения определяет библиотечную функцию qsort(). К счастью List реализован как круговой буфер в массиве, то есть если мы захотим реализовать sort() как метод List, то должны испытать очень мало затруднений:

 

static int cmp (const void * a, const void * b)

{

    return differ(* (void **) a, * (void **) b);

}

 

% List sort {

%casts

if (self -> count) {

    while (self -> begin + self -> count > self -> dim)

        addFirst(self, takeLast(self));

    qsort(self -> buf + self -> begin, self -> count,

                            sizeof self -> buf[0], cmp);

    }

}

 

Если список содержит какие-либо элементы, мы прокручиваем список до тех пор, пока он не будет занимать слитную область буфера, а затем передаём список в qsort(). Функция сравнения отсылает differ() прямо к элементам списка — String_differ была основана на strcmp() и поэтому можно (зло-)употребить её в качестве функции сравнения.

 

Предыдущая  Содержание  Следующая