qsort with limited boundaries in K&R | sorting procedure doesn't continue on next positions in strings

StackOverflow https://stackoverflow.com/questions/11968050

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

Was it helpful?

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 0th (first) element of the array and the nlines-1 (last) element.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top