0

I have this project where I need to create an array, split it into two, and then sort each array using its own thread, then merge the two arrays back into a single array. Thankfully, the final array doesn't need to be sorted itself.

I wrote this code:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

//Change length of main input array
const int arrLen = 20;
const int mid = arrLen/2;

void swap(int *a, int *b){
    int temp = *a;
    *a = *b;
    *b = temp;
}

void *sort(void *arg){
    int min_pos;
    for(int a=0; a<arrLen-1; a++){
        min_pos = a;
        for(int b=a+1; b<arrLen; b++){
            if(array[b] < array[min_pos]){
                min_pos = b;
            }
        }
        swap(&array[min_pos], &array[a]);
    }
}


void printResult(int array[]){

    for(int k=0; k<arrLen/2; k++){
        printf("Num%d: %d\n", k, array[k]);
    }
}

//Adds random values to each position in a given array
void arrayCreator(int array[]){
    int random;
    for(int i=0; i<arrLen; i++){
        random = rand() % 100;
        array[i] = random;
    }
    
}

void main(){

    printf("Program Initialized...\n");
    int mainArray [arrLen], firstHalf[mid], secondHalf[mid], random;
    time_t t;
    srand((unsigned) time(&t));
    
    //Populate mainArray
    for(int i=0; i<arrLen; i++){
        mainArray[i] = rand()%100;
    }   
    
    printf("Array created...\n");
    
    //Split mainArray[] into two seperate arrays
    for(int p=0; p<arrLen; p++){
        if(p<mid){
            firstHalf[p]=mainArray[p];
        }
        else{
            secondHalf[p-mid]=mainArray[p];
        }   
    }
    pthread_t tid1;
    pthread_t tid2;
    pthread_create(&tid1, NULL, sort, (void*)firstHalf);
    //pthread_create(&tid2, NULL, sort, secondHalf);
    printResult(firstHalf);
    //printResult(secondHalf);
    
}

How can I get the sort function to access my array?

4
  • 1
    You're completely new to C and you're already doing multi-threading? Commented Jun 28, 2022 at 0:12
  • 1
    Welcome to Stack Overflow. "but I'm having trouble getting my sort function to access my array." What exactly do you mean by this? Which array is "my array"? What kind of "trouble" are you having, and what observable behaviour leads you to the conclusion that there is "trouble" with "accessing" it? What happens when you run the code, and how is that different from what is supposed to happen? Please read How to Ask and try to communicate more clearly. Commented Jun 28, 2022 at 0:19
  • Hint: where the code says for(int a=0; a<arrLen-1; a++){, where does the value of arrLen come from? What is that value? What does that indicate? Now - how long is the array data that you actually are passing? (Hint: what was the purpose of the code that created firstHalf and secondHalf?) Final hint: try looking at how the standard library sort is implemented. Notice how it accepts a parameter to indicate the length of the array? Why do you suppose that is? Commented Jun 28, 2022 at 0:22
  • Hint: where the code says void *sort(void *arg){, what do you expect that to mean? In particular, what does the arg part mean? Where the code says if(array[b] < array[min_pos]){ inside that function, what do you expect the array part to refer to? Why and how? Did you mean for it to refer to the data that is passed in? Is that named array? Do you see the problem? Commented Jun 28, 2022 at 0:24

2 Answers 2

1
  • First, I would look at the signature of the standard function qsort and provide the same interface for your sort function. I'd also rename it into bubble_sort since it's doing bubble sorting. Your function would then look like this:
    void bubble_sort(void *ptr, size_t arrLen, size_t elem_size,
                     int (*comp)(const void *, const void *)) {
    
        char *array = ptr; // to be able to do pointer arithmetic
    
        for (size_t a = 0; a < arrLen - 1; a++) {
            for (size_t b = a + 1; b < arrLen; b++) {
                if (comp(array + a * elem_size, array + b * elem_size) > 0) {
                    swap(array + a * elem_size, array + b * elem_size, elem_size);
                }
            }
        }
    }
    
    • elem_size is the size of the elements you want to sort, which will be set to sizeof(int) later.
    • comp is a function taking two void* and returns an int where ...
      • < 0 means *a < *b
      • > 0 means *a > *b
      • == 0 means *a == *b
  • swap also takes the elem_size parameter to be able to swap objects of any size. Implemented, it could look like this:
    void swap(void *a, void *b, size_t elem_size) {
        char tmp[elem_size];
        memcpy(tmp, a, elem_size);
        memcpy(a, b, elem_size);
        memcpy(b, tmp, elem_size);
    }
    

Now, you can't start a thread by calling bubble_sort directly. A thread start routine only takes a single void* as an argument so we need some way of passing all the necessary arguments on. We can package them in a struct like this:

struct sort_thread_args {
    pthread_t tid;
    void *array;
    size_t arrLen;
    size_t elem_size;
    int (*comp_func)(const void *, const void *);
};

void *sort_thread(void *arg) {              // the thread start routine
    struct sort_thread_args *ta = arg;
    bubble_sort(ta->array, ta->arrLen, ta->elem_size, ta->comp_func);
    return NULL;
}

As can be seen above, the struct contains all the necessary information to call bubble_sort + the thread id, which I've stored there for convenience only. It's not needed by the thread itself.

The above functions are type agnostic so you can use these to sort any contiguous array, either by calling bubble_sort directly or in a thread.

Since you'll be using this to sort arrays of int, we need a comparison function for ints which does what was described above:

int comp_int(const void *va, const void *vb) {
    const int *a = va;
    const int *b = vb;
    if (*a < *b) return -1;
    if (*a > *b) return 1;
    return 0;
}

Then for sorting half the array in one thread and the other half in another thread, I suggest that you don't copy the contents of mainArray to new arrays. Just leave the content in mainArray and tell each thread where to start sorting and how many elements it should sort.

Example:

#define Size(x) (sizeof(x) / sizeof *(x))

int main() {
    srand((unsigned)time(NULL));
    puts("Program Initialized...");

    int arrLen = 35;       // just an example to show that it handes uneven amounts too
    int mainArray[arrLen];

    // Populate mainArray
    for (size_t i = 0; i < Size(mainArray); i++) {
        mainArray[i] = rand() % 100;
    }
    puts("Array created...");

    // print the created array
    for (size_t i = 0; i < Size(mainArray); ++i) printf("%2d ", mainArray[i]);
    putchar('\n');

    puts("Running sorting threads...");
    struct sort_thread_args ta[2];      // 2 for 2 threads

    for (size_t i = 0; i < Size(ta); ++i) {
        // element index for where this thread should start sorting:
        size_t base = i * Size(mainArray) / Size(ta);

        // prepare the arguments for this thread:
        ta[i] = (struct sort_thread_args) {
            .array = mainArray + base,    // points at the first element for this thread
            .arrLen = (i + 1) * Size(mainArray) / Size(ta) - base,
            .elem_size = sizeof(int),
            .comp_func = comp_int     // the comparison function we made above
        };

        // and start the thread:
        pthread_create(&ta[i].tid, NULL, sort_thread, &ta[i]);
    }

    puts("Joining threads");
    for (size_t i = 0; i < Size(ta); ++i) {
        pthread_join(ta[i].tid, NULL);
    }

    puts("Result:");
    for (size_t i = 0; i < Size(mainArray); ++i) printf("%2d ", mainArray[i]);
    putchar('\n');
}

Demo

Sign up to request clarification or add additional context in comments.

Comments

0

Simply assign arg to your array variable in order to convert from void * to int *.

void *sort(void *arg){
    int min_pos;
    int *array = arg;
    for(int a=0; a<arrLen-1; a++){
        min_pos = a;
        for(int b=a+1; b<arrLen; b++){
            if(array[b] < array[min_pos]){
                min_pos = b;
            }
        }
        swap(&array[min_pos], &array[a]);
    }
}

2 Comments

If that is what you've identified as the problem being asked about, then it is clearly just a typo; it would make at least as much sense to just use arr directly, or change the parameter name to array to match. On the other hand, if you suppose that OP misunderstands array indexing/pointer arithmetic equivalency, or misunderstands pointer decay, then that is surely a common duplicate.
You can't change the parameter name to array because you can't index void *. You need a new variable to have the correct type.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.