Язык программирования Си (Ритчи, Керниган) - страница 89

> } else {

>  printf("ошибка: слишком много строк\n");

>  return 1;

> }

>}


>#define MAXLEN 1000 /* максимальная длина строки */

>int getline(char *, int);

>char *alloc(int);


>/* readlines: чтение строк */

>int readlines(char *lineptr[], int maxlines)

>{

> int len, nlines;

> char *p, line[MAXLEN];


> nlines = 0;

> while ((len = getline(line, MAXLEN)) › 0)

>  if (nlines ›= maxlines || (p = alloc(len)) == NULL)

>   return -1;

>  else {

>   line[len-1] = '\0'; /* убираем символ \n */

>   strcpy(p, line);

>   lineptr[nlines++] = p;

>  }

> return nlines;

>}


>/* writelines: печать строк */

>void writelines(char *lineptr[], int nlines)

>{

> int i;

> for (i = 0; i ‹ nlines; i++)

>  printf("%s\n", lineptr[i]);

>}

Функция getline взята из параграфа 1.9. Основное новшество здесь - объявление lineptr:

>char *lineptr[MAXLINES];

в котором сообщается, что lineptr есть массив из MAXLINES элементов, каждый из которых представляет собой указатель на char. Иначе говоря, lineptr[i] - указатель на символ, а *lineptr[i] - символ, на который он указывает (первый символ i-й строки текста).

Так как lineptr - имя массива, его можно трактовать как указатель, т. е. так же, как мы это делали в предыдущих примерах, и writelines переписать следующим образом:

>/* writelines: печать строк */

>void writelines(char *lineptr[], int nlines)

>{

> while (nlines-- › 0)

>  printf("%s\n", *lineptr++);

>}

Вначале *lineptr указывает на первую строку: каждое приращение указателя приводит к тому, что *lineptr указывает на следующую строку, и делается это до тех пор, пока nlines не станет нулем.

Теперь, когда мы разобрались с вводом и выводом, можно приступить к сортировке. Быструю сортировку, описанную в главе 4, надо несколько модифицировать: нужно изменить объявления, а операцию сравнения заменить обращением к strcmp. Алгоритм остался тем же, и это дает нам определенную уверенность в его правильности.

>/* qsort: сортирует v[left]…v[right] по возрастанию */

>void qsort(char *v[], int left, int right)

>{

> int i, last;

> void swap(char *v[], int i, int j);


> if (left ›= right) /* ничего не делается, если в массиве */

>  return; /* менее двух элементов */


> swap(v, left, (left+right)/2);

> last = left;

> for(i = left+1; i ‹= right; i++)

>  if (strcmp(v[i], v[left]) ‹ 0)

>   swap(v, ++last, i);

> swap(v, left, last);

> qsort(v, left, last-1);

> qsort(v, last+1, right);

>}

Небольшие поправки требуются и в программе перестановки.

>/* swap: поменять местами v[i] и v[j] */

>void swap(char *v[], int i, int j)

>{

> char *temp;

> temp = v[i];

> v[i] = v[j];

> v[j] = temp;

>}

Так как каждый элемент массива v (т. е. lineptr) является указателем на символ,