검색결과 리스트
글
포인터도 일종의 변수이기 때문에 포인터들로 이루어진 배열도 가능하다. 설명을 위해서 문자로 이루어진 행의 순서를 사전순서로 정렬하는 프로그램을 예로 들겠다.
제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에서 사용가능한 배열에 입력을 지정해보라 프로그램 수행이 얼마나 빨라지는지 보라.
'프로그래밍 > C' 카테고리의 다른 글
5.8 포인터 배열의 초기화(Initialization of Pointer Arrays) (0) | 2014.11.04 |
---|---|
5.7 다차원 배열(Multi-dimensional Arrays) (0) | 2014.11.04 |
5.5 문자 포인터와 함수(Character Pointers and Functions) (0) | 2014.11.03 |
5.4 번지 연산(Address Arithmetic) (0) | 2014.11.03 |
5.3 포인터와 배열(Pointers and Arrays) (0) | 2014.11.03 |
RECENT COMMENT