C quick sort function keeps crashing - c

Part of an assignment I'm doing for school involved building a quick sort to sort an array. I'm pretty sure I have it close, however whenever I call it, it crashes on me
void quickSort(double * array, unsigned int size, int start, int stop)
{
int swapIndex = start;
int pivot = start;
double temp;
if (size > 1)
{
for (int i = pivot + 1; i < stop; ++i)
{
if (array[pivot] > array[i])
{
++swapIndex;
temp = array[i];
array[i] = array[swapIndex];
array[swapIndex] = temp;
}
}
temp = array[swapIndex];
array[swapIndex] = array[pivot];
array[pivot] = temp;
quickSort(array, size, start, swapIndex);
quickSort(array, size, swapIndex, size);
}
}
http://pastebin.com/Ccv4KP3j

N.B. This answer's based off the pastebin link as of 27/2/2016
First of all your function has the wrong return type - quicksort works in-place, meaning that it doesn't create any new arrays; it sorts the array you passed to it. It will work perfectly as a void function.
Remember that in C, arrays can only be passed by reference, i.e. every recursive call to quicksort deals with exactly the same array.
Your quicksort should work like so:
double arr[] = {12, -2, 4, 5, 2, 1};
quicksort(arr, 0, 5);
// arr is now sorted
int i;
for (i=0; i<6; i++){
printf("%f, ", arr[i]);
}
printf("\n");
// prints "-2, 1, 2, 4, 5, 12"
For the sake of clarity, I'd recommend writing a function void doubleSwap(double *a, double* b) to take care of all the element swapping without muddying your code.
The reason your code results in stack overflows is twofold:
The initial if guard needs to check if start and stop differ by
more than one, not just if they're different.
The 'swapIndex' variable always overlaps the pivot cell, resulting in
confusion as the pivot value gets mutated before the
whole array is processed. It can be fixed by setting pivot to
stop - 1.
Here is a pastebin of my version of your code, but before looking at it, try to debug it yourself using a bunch of printfs.
Also note that you don't have to pass the whole array to qsort - you can replace quickSort(array, swapIndex, stop) with quickSort(array + swapIndex, 0, stop - swapIndex), allowing you to get rid of start altogether because it's always zero.
void doubleSwap(double *a, double*b){
double temp = *a;
*a = *b;
*b = temp;
}
void quickSort(double * array, int start, int stop)
{
int pivot = stop - 1;
int swapIndex = start;
int i;
if (start < stop - 1) {
for (i = start; i < stop; i++) {
if (array[i] < array[pivot]){
doubleSwap(array + swapIndex, array + i);
swapIndex++;
}
}
// Note that `array + swapIndex` is equivalent to `&(array[swapIndex])`
doubleSwap(array + swapIndex, array + pivot);
fprintf(stderr, "swapIndex = %d start = %d stop = %d\n", swapIndex, start, stop);
for (i = 0; i< NELEMS; i++){
fprintf(stderr, "%3f, ", array[i]);
}
fprintf(stderr, "\n");
quickSort(array, start, swapIndex);
quickSort(array, swapIndex, stop);
}
}

Related

My function for generating random numbers isn't going past 500000

I'll get right into my problem. So basically what I want to do is to generate an array of random numbers of different amounts. So one with 10,000, 50,000, 100,000, 500,000, 600,000, etc. Then I would sort them using quicksort and print the sorted array to the screen. Additionally, the time taken for it to run would be recorded and printed as well. The only part I'm having problems with however is generating the array. For some reason generating past 500,000 random numbers does not work and returns this:
Process exited after 2.112 seconds with return value 3221225725
Press any key to continue . . .
([1]: https://i.stack.imgur.com/m83el.png)
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void randNums(int array[], int range) {
int i, num;
for (i = 0; i < range; i++) {
num = rand() % range;
array[i] = num;
}
}
//prints elements of given array
void display(int array[], int size) {
int i;
for (i = 0; i < size; i++) {
printf("#%d. %d\n", i, array[i]);
}
}
//displays time taken for sorting algorithm to run
void timeTaken(char sortingAlgo[], int size, clock_t start, clock_t end) {
double seconds = end - start;
double milliseconds = seconds / 1000;
printf("Time taken for %s Sort to sort %d numbers was %f milliseconds or %f seconds",
sortingAlgo, size, milliseconds, seconds);
}
//quick sort
void quickSort(int array[], int first, int last) {
int i, j, pivot, temp;
if (first < last) {
pivot = first;
i = first;
j = last;
while (i < j) {
while (array[i] <= array[pivot] && i < last)
i++;
while (array[j] > array[pivot])
j--;
if (i < j) {
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
temp = array[pivot];
array[pivot] = array[j];
array[j] = temp;
quickSort(array, first, j - 1);
quickSort(array, j + 1, last);
}
}
int main() {
int size = 600000;
int myArray[size];
time_t end, start;
int first, last;
randNums(myArray, size);
first = myArray[0];
last = sizeof(myArray) / sizeof(myArray[0]);
time(&start);
quickSort(myArray, first, last);
time(&end);
display(myArray, size);
timeTaken("Quick", size, start, end);
return 0;
}
Any help would be greatly appreciated, Thank you!
There's a lot of little bugs in this code that aren't too difficult to resolve. I'll try and break it down here in this refactoring and cleanup:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void randNums(int* array, int range) {
// Declare iterator variables like `i` within the scope of the iterator.
for (int i = 0; i < range; i++) {
// No need for a single-use variable here, just assign directly.
array[i] = rand () % range;
}
}
void display(int* array, int size) {
// for is not a function, it's a control flow mechanism, so
// it is expressed as `for (...)` with a space. `for()` implies
// it is a function, which it isn't.
for (int i = 0; i < size; i++) {
printf("#%d. %d\n", i, array[i]);
}
}
void timeTaken(char* sortingAlgo, int size, clock_t start, clock_t end) {
// Time calculation here needs to account for the fact that clock_t
// does not use seconds as units, it must be converted
// https://en.cppreference.com/w/c/chrono/clock_t
printf(
"Time taken for %s Sort to sort %d numbers was %.6f seconds",
sortingAlgo,
size,
((double) (end - start)) / CLOCKS_PER_SEC
);
}
void quickSort(int* array, int first, int last) {
// Establish a guard condition. Rest of the function is no longer
// nested in a control flow structure, so it simplifies the code.
if (first >= last) {
return;
}
int pivot = first;
int i = first;
int j = last;
// Use `while (...)` as it's also a control flow structure.
while (i < j) {
// Adding space around operators improves clarity considerably. Unspaced
// elements like `a->b()` are supposed to stand out and not be confused
// with visually similar `a>>b()` which does something very different.
while (array[i] <= array[pivot] && i < last) {
i++;
}
// Use surrounding braces on all blocks, even single-line ones, as this
// can avoid a whole class of errors caused by flawed assumptions.
// while (...) { ... }
while (array[j] > array[pivot]) {
j--;
}
if (i < j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
int temp = array[pivot];
array[pivot] = array[j];
array[j] = temp;
quickSort(array, first, j - 1);
quickSort(array, j + 1, last);
}
int main(int argc, char** argv) {
int size = 600000;
// If an argument was given...
if (argc > 1) {
// ...use that as the size parameter instead.
size = atol(argv[1]);
}
// Allocate an array of sufficient size
int* numbers = calloc(size, sizeof(int));
randNums(numbers, size);
// time_t has at best second-level precision, it's very inaccurate.
// Use clock_t which gives far more fidelity.
clock_t start = clock();
// This function takes *offsets*, not values.
quickSort(numbers, 0, size - 1);
clock_t end = clock();
display(numbers, size);
timeTaken("Quick", size, start, end);
free(numbers);
return 0;
}
The number one bug here was calling quickSort() incorrectly:
// Represents first *value* in the array
first = myArray[0]; // Should be: 0
// Rough calculation of the size of the array, but this is off by one
last = sizeof(myArray)/sizeof(myArray[0]); // Should be: size - 1
quickSort(myArray, first, last);

Segmentation in QuickSort

I'm getting a segmentation fault:11 when I try to run this QuickSort, but it compiles fine. I'm running it with a driver, which is why I use quicksort() and quicksortR(). What's causing the segmentation?
/* -------- Quick sort stuff starts here --------- */
int partition(int array[], int start, int stop) {
int compars = 0;
int pivot = array[stop];
int i = start - 1;
for (int j = start; j <= stop - 1; j++) {
if (array[j] <= pivot) {
i++;
int temp = array[j];//swaps values of i and j
array[j] = array[i];
array[i] = temp;
}
compars++;
}
int temp = array[i + 1];
array[i + 1] = array[stop];
array[stop] = temp;
return compars;
}
int quickSortR(int array[], int start, int stop) {
int compars = 0;
int mid = array[stop];
if (start < stop) {
compars = compars + partition(array, start, stop);
quickSortR(array, start, mid - 1);
quickSortR(array, mid+1, stop);
}
return compars;
}
int quickSort(int array[], int n) {
return quickSortR(array, 0, n);
}
/* ----------- end quick sort stuff ----------------- */
You call quicksort with the number of elements of the array as the stop argument, but you initialize the pivot as int pivot = array[stop];. You are reading past the end of the array. Undefined behavior.
There are probably other problems in the code, but this alone explains the crash.
I'm getting a segmentation fault:11 when I try to run this QuickSort, but it compiles fine
Please note: program compiling means compiler understands what you want your program to do. In no way compiler checks if what your program does makes any sense whatsoever.
If it knew what you want to do why wouldn't it write the program itself?

Is there a way to iterate over order?

How can one iterate through order of execution?
I am developing a piece of software that have several steps to compute over some data, and i was thinking in may changing the order of those steps pragmatically so i can check what would be the best order for some data.
Let me exemplify: I have let's say 3 steps (it's actually more):
stepA(data);
stepB(data);
stepC(data);
And I want a contraption that allow me to walk thought every permutation of those steps and then check results. Something like that:
data = originalData; i=0;
while (someMagic(&data,[stepA,stepB,stepC],i++)){
checkResults(data);
data = originalData;
}
then someMagic execute A,B then C on i==0. A, C then B on i==1. B, A then C on i==2 and so on.
You can use function pointers, maybe something like the following:
typedef void (*func)(void *data);
int someMagic(void *data, func *func_list, int i) {
switch (i) {
case 0:
func_list[0](data);
func_list[1](data);
func_list[2](data);
break;
case 1:
func_list[0](data);
func_list[2](data);
func_list[1](data);
break;
case 2:
func_list[1](data);
func_list[0](data);
func_list[2](data);
break;
default: return 0;
}
return 1;
}
func steps[3] = {
stepA,
stepB,
stepC
}
while (someMagic(&data, steps, i++)) {
....
}
The key is to find a way to iterate over the set of permutations of the [0, n[ integer interval.
A permutation (in the mathematical meaning) can be seen as a bijection of [0, n[ into itself and can be represented by the image of this permutation, applied to [0, n[.
for example, consider the permutation of [0, 3[:
0 -> 1
1 -> 2
2 -> 0
it can be seen as the tuple (1, 2, 0), which in C, translate naturally to the array of integers permutation = (int []){1, 2, 0};.
Suppose you have an array of function pointers steps, then for each permutation, you'll then want to call steps[permutation[i]], for each value of i in [0, n[.
The following code implements this algorithm:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
static void stepA(int data) { printf("%d: %s\n", data, __func__); }
static void stepB(int data) { printf("%d: %s\n", data, __func__); }
static void stepC(int data) { printf("%d: %s\n", data, __func__); }
static void (* const steps[])(int) = {stepA, stepB, stepC,};
static int fact(int n) { return n == 0 ? 1 : fact(n - 1) * n; }
static int compare_int(const void *pa, const void *pb)
{
return *(const int *)pa - *(const int *)pb;
}
static void get_next_permutation(int tab[], size_t n)
{
int tmp;
unsigned i;
unsigned j;
unsigned k;
/* to find the next permutation in the lexicographic order
* source: question 4 (in french, sorry ^^) of
* https://liris.cnrs.fr/~aparreau/Teaching/INF233/TP2-permutation.pdf
. */
/* 1. find the biggest index i for which tab[i] < tab[i+1] */
for (k = 0; k < n - 1; k++)
if (tab[k] < tab[k + 1])
i = k;
/* 2. Find the index j of the smallest element, bigger than tab[i],
* located after i */
j = i + 1;
for (k = i + 1; k < n; k++)
if (tab[k] > tab[i] && tab[k] < tab[j])
j = k;
/* 3. Swap the elements of index i and j */
tmp = tab[i];
tab[i] = tab[j];
tab[j] = tmp;
/* 4. Sort the array in ascending order, after index i */
qsort(tab + i + 1, n - (i + 1), sizeof(*tab), compare_int);
}
int main(void)
{
int n = sizeof(steps) / sizeof(*steps);
int j;
int i;
int permutation[n];
int f = fact(n);
/* first permutation is identity */
for (i = 0; i < n; i++)
permutation[i] = i;
for (j = 0; j < f; j++) {
for (i = 0; i < n; i++)
steps[permutation[i]](i);
if (j != f - 1)
get_next_permutation(permutation, n);
}
return EXIT_SUCCESS;
}
The outer loop in main, indexed by j, iterates over all the n! permutations, while the inner one, indexed by i, iterates overs the n steps.
The get_next_permutation modifies the permutation array in place, to obtain the next permutation in the lexicographical order.
Note that it doesn't work when the permutation in input is the last one (n - 1, ..., 1, 0), hence the if (j != f - 1) test.
One could enhance it to detect this case (i isn't set) and to put the first permutation (0, 1, ..., n - 1) into the permutation array.
The code can be compiled with:
gcc main.c -o main -Wall -Wextra -Werror -O0 -g3
And I strongly suggest using valgrind as a way to detect off-by-one errors.
EDIT: I just realized I didn't answer the OP's question precisely. The someMagic() function would allow a direct access to the i-th permutation, while my algorithm only allows to compute the successor in the lexicographic order. But if the aim is to iterate on all the permutations, it will work fine. Otherwise, maybe an answer like this one should match the requirement.
I've come to a solution that is simple enough:
void stepA(STRUCT_NAME *data);
void stepB(STRUCT_NAME *data);
void stepC(STRUCT_NAME *data);
typedef void (*check)(STRUCT_NAME *data);
void swap(check *x, check *y) {
check temp;
temp = *x;
*x = *y;
*y = temp;
}
void permute(check *a, int l, int r,STRUCT_NAME *data) {
int i, j = 0, score;
HAND_T *copy, *copy2, *best_order = NULL;
if (l == r) {
j = 0;
while (j <= r) a[j++](data);
} else {
for (i = l; i <= r; i++) {
swap((a + l), (a + i));
permute(a, l + 1, r, data);
swap((a + l), (a + i));
}
}
}
check checks[3] = {
stepA,
stepB,
stepC,
};
int main(void){
...
permute(checks,0,2,data)
}

C-Lomuto Quicksort Exe does not work

#include <stdio.h>
#define ARRAY_SIZE 10
void lomuto (int A[], int l, int r, int smallerAtLeft)
{
if (smallerAtLeft == 1) //move elements smaller than pivot to the left and the greater ones to the right
{
int tmp, tmp2,pivot,i,j;
pivot = A[r];
i = l-1;
for (j =0; j<r-1; j++)
{
if (A[j] <= pivot)
{
i++;
tmp = A[i];
A[i] = A[j];
A[j] = tmp;
}
}
tmp2 = A[i+1];
A[i+1] = A[r];
A[r] = tmp2;
}
if (smallerAtLeft == 0) //move elements smaller than pivot to the right and the greater ones to the left
{
int tmp3, tmp4,pivot,i,j;
pivot = A[r];
i = l-1;
for (j=0; j<r-1; j++)
{
if (A[j]>= pivot)
{
i++;
tmp3 = A[i];
A[i] = A[j];
A[j] = tmp3;
}
}
tmp4 = A[i+1];
A[i+1] = A[r];
A[r] = tmp4;
}
}
void quicksort (int A[], int l, int r, int ascending)
{
lomuto (A,l,r,ascending);
}
int main()
{
int testarray;
int testArray[ARRAY_SIZE] = {4, 2, 5, 3, 6, 7, 8, 1, 0};
quicksort (testarray,0,8,1);
return testarray;
}
Good evening.
Usually I search almost every forum and deepest threads for dubiety in my codes.
But this time I did not found an answer that could help me. I would be so thankful if anyone could tell my why the code-exe stops working but during compiling there is no error showing onscreen.
We have to implement the quicksort algorithm with the lomuto-partitioning. If the variable "smallerAtLeft" ist equal to 1, the array should be ordered by an increasing property and if its equal to 0 decreasingly.
Furthermore we have to implement to void functions like you see in the code. The "lomuto-fct" and the "quicksort-fct" that contains the lomuto one.
Maybe this Reverse-Lomuto-Thread will help some other people too in the future..
I don't think you understand what the return value from main is and what it's used for. It is usually an indicator of success and failure, with the typical values 0 for success and a small positive value for failure. There are even macros defined for this purpose in the <stdlib.h> header file: EXIT_SUCCESS and EXIT_FAILURE.
If you want to see the sorted array you need to print it:
printf("Sorted array = {");
for (unsigned i = 0; i < ARRAY_SIZE; ++i)
{
printf(" %d", testArray[i]);
}
printf(" }\n");
That of course requires you to pass the actual array to your sorting function.

Quicksort string array in C

I'm writing a quicksort algorithm to sort an array of strings.
The problem is that my array with the data seem to be overwritten with something right after i allocate the right and left quicksort arrays, because i print the array and its all there, but after i use malloc to allocate the others arrays, i print it again and i'm missing some elements.
Here's the output:
Pivot: 2
Emma, Olivia, Victoria, Gwyneth, Chloe, Hayley, Scarlett,
Emma, Olivia, Victoria, Gwyneth, , , ,
Anyone knows whats happening? What am missing?
char **concatenate(char **array1, int n1, char *pivot, char **array2, int n2, int len){
int i=0, j=0;
int elements = n1 + n2 + 1;
// alocating array
char **concat = (char**) malloc(sizeof(*concat) * elements);
concat[0] = (char*) malloc(sizeof(*concat) * elements * len);
for(i=1; i<elements; i++)
concat[i] = &(concat[0][i*len]);
// concatenating
for(i=0; i<n1; i++)
concat[i] = array1[i];
concat[i++] = pivot;
for(j=0; j<n2; j++)
concat[i++] = array2[j];
// returning
return concat;
}
char **quicksort(char **array, int elements, int len){
// array is already sorted
if(elements < 2)
return array;
int pivot;
int i=0, l=0, r=0;
// selecting the pivot (median)
if(elements % 2 == 0)
pivot = ((elements + 1) / 2) -1;
else
pivot = (elements / 2) -1;
//REMOVE
printf("Pivot: %d\n", pivot);
for(i=0; i<elements; i++)
printf("%s, ", array[i]);
printf("\n");
// alocating arrays
char **left = (char**) malloc(sizeof(*left) * pivot);
left[0] = (char*) malloc(sizeof(*left) * pivot * len);
for(i=1; i<pivot; i++)
left[i] = &(left[0][i*len]);
char **rigth = (char**) malloc(sizeof(*rigth) * pivot);
rigth[0] = (char*) malloc(sizeof(*rigth) * pivot * len);
for(i=1; i<pivot; i++)
rigth[i] = &(rigth[0][i*len]);
//REMOVE
for(i=0; i<elements; i++)
printf("%s, ", array[i]);
printf("\n");
//quicksorting
for(i=0; i<elements; i++){
if(array[i] == array[pivot])
continue;
int comp = strcmp(array[i], array[pivot]);
//REMOVE
printf("%d: strcmp %s, %s is %d\n", i, array[i], array[pivot], comp);
if(comp < pivot)
left[l++] = array[i];
else
rigth[r++] = array[i];
}
//REMOVE
printf("concatenate(");
for(i=0; i<l; i++)
printf("%s ", left[i]);
printf("|%s| ", array[pivot]);
for(i=0; i<r; i++)
printf("%s ", rigth[i]);
printf(")\n");
// recursion and return
return concatenate(quicksort(left, l, len), l, array[pivot], quicksort(rigth, r, len), r, len);
}
int main(int argc, char *argv[]){
int i, j, aux;
char **teste = (char**) malloc(sizeof(*teste) * 7);
teste[0] = (char*) malloc(sizeof(*teste) * 7 * 128);
for(i=1; i<7; i++)
teste[i] = &(teste[0][i*128]);
teste[0] = "Emma";
teste[1] = "Olivia";
teste[2] = "Victoria";
teste[3] = "Gwyneth";
teste[4] = "Chloe";
teste[5] = "Hayley";
teste[6] = "Scarlett";
quicksort(teste, 7, 128);
printf("AFTER\n");
for(i=0; i<7; i++)
printf("%s, ", teste[i]);
printf("\n");
return 0;
}
There is zero reason to allocate for quicksort, and in fact the function can easily suffice in your case with a simple interface of quicksort(char *arr[], unsigned int len), using pointer-math for the subsequence invocations.
Provide a swap algorithm for exchanging pointers:
void swap_str_ptrs(char const **arg1, char const **arg2)
{
const char *tmp = *arg1;
*arg1 = *arg2;
*arg2 = tmp;
}
Then the algorithm is:
void quicksort_strs(char const *args[], unsigned int len)
{
unsigned int i, pvt=0;
if (len <= 1)
return;
// swap a randomly selected value to the last node
swap_str_ptrs(args+((unsigned int)rand() % len), args+len-1);
// reset the pivot index to zero, then scan
for (i=0;i<len-1;++i)
{
if (strcmp(args[i], args[len-1]) < 0)
swap_str_ptrs(args+i, args+pvt++);
}
// move the pivot value into its place
swap_str_ptrs(args+pvt, args+len-1);
// and invoke on the subsequences. does NOT include the pivot-slot
quicksort_strs(args, pvt++);
quicksort_strs(args+pvt, len - pvt);
}
Thats everything. including the partitioning.
How It Works
There are two general recursive quicksort algorithms: the squeeze, and the sweep. This is the sweep algorithm. We march up the sequence, swapping any element "less" than than pivot value (which is swapped to the end of the sequence before the loop starts) to a target slot, the index of which is initially the beginning of the sequence and increases with each swap operation. When the "sweep" is finished, the pvt index is where the pivot value belongs, as everything below that slot is "less" than the that value. So one more swap is made to put the pivot value into position. After that we have two partitions, which are recursed. It is vital that the slot we just identified as the pivot location is not included in either of those partitions. It is the only value we know is in its final resting place.
Test Harnass
Including the above code, we test this with a basic set of strings purposely out of order:
void print_list(char const *args[], unsigned len)
{
unsigned i=0;
for (;i<len;++i)
puts(args[i]);
}
int main()
{
char const *args[] =
{
"this", "is", "a", "test", "of", "quicksort", "with", "strings"
};
srand((unsigned)time(NULL));
quicksort_strs(args, sizeof(args)/sizeof(*args));
print_list(args, sizeof(args)/sizeof(*args));
return 0;
}
Output
a
is
of
quicksort
strings
test
this
with
Non-recursive implementation
It should be noted that the above algorithm lends itself beautifully to a non-recursive implementation. A local dynamic stack is used for holding pairs of data: an pointer and a length. Optimized to not push trivial segments (segments of length 1 or 0) on to the stack, one implementation would like like this:
void quicksort_strs(char const *args[], unsigned int len)
{
// holds our non-recursive stack of segments
struct segment
{
char const **arr;
unsigned int len;
struct segment* next;
} *stack = NULL;
stack = malloc(sizeof(*stack));
stack->arr = args;
stack->len = len;
stack->next = NULL;
while (stack != NULL)
{
unsigned int i, pvt=0;
struct segment *tmp = stack;
stack = stack->next;
// pull values and delete segment record
args = tmp->arr;
len = tmp->len;
free(tmp);
// nothing to unary segments
if (len <= 1)
continue;
// swap a randomly selected value to the last node
swap_str_ptrs(args+((unsigned int)rand() % len), args+len-1);
// reset the pivot index to zero, then scan
for (i=0;i<len-1;++i)
{
if (strcmp(args[i], args[len-1]) < 0)
swap_str_ptrs(args+i, args+pvt++);
}
// move the pivot value into its place
swap_str_ptrs(args+pvt, args+len-1);
// lhs segment push
if (pvt > 1)
{
tmp = malloc(sizeof(*tmp));
tmp->arr = args;
tmp->len = pvt;
tmp->next = stack;
stack = tmp;
}
// rhs segment push
if ((len - ++pvt) > 1)
{
tmp = malloc(sizeof(*tmp));
tmp->arr = args+pvt;
tmp->len = len-pvt;
tmp->next = stack;
stack = tmp;
}
}
}
Obviously having a canned node-stack implementation would shorten this up considerably, but the idea should be readily apparent. A realloc() schema for holding nodes on the end of the "stack" rather than the beginning would be equally interesting, as it would eliminate the need to next pointer management, replaced with a top index instead.
Anyway, good luck, and I hope it helps.

Resources