qsort with limited boundaries in K&R | sorting procedure doesn't continue on next positions in strings
-
26-06-2021 - |
Question
Sorry to bother You with yet another question about K&R programs. But again some things are not clear to me. The program below is used to sort lines saved by readlines function (is it really saving them?) For that purpose we create an array of pointers pointing to each of these lines.
Questions:
[1] Why do we pass qsort(lineptr, 0, nlines-1);
I mean nlines-1 and not just nlines ?
[2] Suppose I entered two lines:
bravo
alfa
now they're pointed from array (I'll make a visualization so don't get mad seeing chars in brackets ;))
*v[] == [lineptr[0] - pointer to bravo][lineptr[1] - pointer to alfa]
according to the algorithm: lineptr[0] is the pivot, so we swap them; last = 0; entering for loop: strcmp of - lineptr[1] is not lexically smaller than lineptr[0]; incrementing i is already finished so we exit for loop. Now we swap last = 0 with left = 0, so nothing happens. They're already in place.
BUT WHAT IF they begin with the same letter eg. abravo and alfa, how would qsort go on to next letter if it only operates on array's indexes from left to right meaning different number of lines not next chars in examined strings.
Please correct me, because all those pointers are driving me crazy.
The whole code:
#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 *lineptr[], int nlines);
void qsort(char *lineptr[], int left, int right);
/* sort input lines */
main()
{
int nlines;
/* number of input lines read */
if ((nlines = readlines(lineptr, MAXLINES)) >= 0) {
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 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 ((len = getline(line, MAXLEN)) > 0)
if (nlines >= maxlines || p = alloc(len) == NULL)
return -1;
else {
line[len-1] = '\0'; /* delete newline */
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]);
}
/* qsort: sort v[left]...v[right] into increasing order */
void 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);
qsort(v, left, last-1);
qsort(v, last+1, right);
}
THANKS IN ADVANCE FOR HELP
Solution
strcmp
compares two strings for lexicographic order. This will take care of using the whole string for comparison, not just the first character.
And the parameter right
takes the index of the right-most index to sort on. If you have an array of length 10, the first element is 0 and the last is 9 (i.e. 10 - 1, which is right -1
). The clue is in the line for (i = left+1; i <= right; i++)
, which loops i from left+1
to right
including both values.
You called it qsort(lineptr, 0, nlines-1);
, so it will include the 0
th (first) element of the array and the nlines-1
(last) element.