포인터도 일종의 변수이기 때문에 포인터들로 이루어진 배열도 가능하다. 설명을 위해서 문자로 이루어진 행의 순서를 사전순서로 정렬하는 프로그램을 예로 들겠다. 

제3장에서 shell sort 함수를 설명한 적이 있다 이 함수는 정수들로 된 배열을 재정렬하는 것이었다. 제 4장에서는 이 함수를 quick sort라는 방법을 사용해서 개선한 적이 있다. 여기서도 같은 알고리즘을 사용하지만 몇 가지 다른점이 있다. 여기서 다루는 것은 문자로 된 행인데,행의 길이도 일정하지 않고 연산 한번으로 이동시킨다든지 복사할 수없다.

이런 문제를 해결하기 위해서는 포인터들의 배열이 필요하다. 각 행은 그 행의 첫 문자를 가리키는 포인터로대표되고,각 행의 포인터들은 모여서 하나의 배열을 이루게 된다.

두 행을 비교하려면 두 행의 포인터를 strcmp로 보내주면 된다. 두 행을 바꾸고자 할때 그 두행을 모두 이동시킬 필요 없이 포인터만 바꿔주면, 두행의 문자들을 바꾸는 작업을 하지 않아도 된다.


프로그램을 작성하는 가장 좋은 방법은 각 단계를 함수로 만들고 전체를 관리하는 주 함수를 작성하는 것이다. 우선 데이터 구조에 대해 생각하면서 입출력을 어떻게 할 것인가를 구상해 본다.

입력 루틴은 문자의 행을 읽어 들여서 어느 곳에 저장해 놓고 각 행의 포인터로 이루어진 배열을 만들어야 한다. 입력이 모두 몇행인지도 세어야 하고 너무 많은 입력이 들어왔을때 행의 수를 -1로 해주는 것과 같은 표시도 해 주어야 한다.

출력 루틴은 정렬된 상태 그대로 각 행을 출력하기만 하면 된다.


#include <stdio.h>

#include <string.h>


#define MAXLINES 5000    /* max #lines to be sorted */

char *lineptr[MAXLINES]; /* pointers to text lines */


int readlines(char *lineptr[],int nlines);

void writelines(char *lineprt[],int nlines);


void my_qsort(char *lineptr[],int left,int right);


/* sort input lines */


int main()

{

    int nlines; /* numer of input lines read */

    

    if ((nlines = readlines(lineptr,MAXLINES))>=0) {

        my_qsort(lineptr, 0, nlines-1);

        writelines(lineptr, nlines);

        return 0;

    } else {

        printf("error: input too big to sort\n");

        return 1;

    }

}


#define MAXLEN 1000 /* max length of any input line */

int my_getline(char*,int);

char *alloc(int);


/* readlines: read input lines */

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

{

    int len,nlines;

    char *p,line[MAXLEN];

    

    nlines = 0;

    while ((lin = my_getline(line, MAXLEN))>0)

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

            return -1;

        else{

            line[len-1] = '\0'; /* delete mewline */

            strcpy(p, line);

            lineptr[nlines]=p;

        }

    return nlines;

}


/* writelines: write output lines */

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]는 포인터가 가리키는 문자(한 행의 첫 문자)가 된다.

lineptr는 배열의 이름이므로 역시 포인터로 처리될 수있다. 그러므로 위 프로그램의 writelines함수는 다음과 같이 해도 된다.


/* writelines: write output lines */

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

{

    while (nlines-- > 0)

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

}


처음 *lineptr는 첫 행을 가리키고 있다. *lineptr가 하나씩 증가한다는 것은 다음해으 그다음 행으로 지시하는 행이 바뀐다는 뜻이다. while 루프에서 nlines 를 1씩 감소시키면서 nlines가 0이 될때까지 출력을 계속한다

지금까지는 입출력 부분에 대해서 살펴보았다 재정렬 하는 부분은 제 4장에 있던 quicksort프로그램을 조금만 고쳐서 사용하면 된다. 선언 부분을 좀 고치고 비교하는 부분을 strcmp 함수를 사용하면 된다 프로그램은 다음과 같다


/* qsort: sort v[left] ... v[right] into increasing order */

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

{

    int i,last;

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

    

    if(left >= right) /* do nothing if array contains */

        return;       /* fewer than two elements */

    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);

    my_qsort(v, left, last-1);

    my_qsort(v, last+1, right);

}


마찬가지로 swap함수도 조금만 고치면 사용할수 있다


/* swap: interchange v[i] and v[j] */

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

{

    char *temp;

    

    temp = v[i];

    v[i] = v[j];

    v[j] = temp;

}


배열 v의 각 요소는 문자형의 포인터 이므로 temp 또는 문자형의 포인터 여야 한다.


예제 5-7 readlines 프로그램을 고쳐서 alloc 함수를 사용하지 않고 main에서 사용가능한 배열에 입력을 지정해보라 프로그램 수행이 얼마나 빨라지는지 보라.