To pass an array by reference in C - arrays

I am trying to modify this merge sort codes from GeekstoGeeks with passing an array by reference.
/* C program for Merge Sort */
#include <stdio.h>
#include <stdlib.h>
// Merges two subarrays of arr[].
// First subarray is arr[l..m]
// Second subarray is arr[m+1..r]
void merge(int arr[], int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
/* create temp arrays */
int L[n1], R[n2];
/* Copy data to temp arrays L[] and R[] */
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1 + j];
/* Merge the temp arrays back into arr[l..r]*/
i = 0; // Initial index of first subarray
j = 0; // Initial index of second subarray
k = l; // Initial index of merged subarray
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
}
else {
arr[k] = R[j];
j++;
}
k++;
}
/* Copy the remaining elements of L[], if there
are any */
while (i < n1) {
arr[k] = L[i];
i++;
k++;
}
/* Copy the remaining elements of R[], if there
are any */
while (j < n2) {
arr[k] = R[j];
j++;
k++;
}
}
/* l is for left index and r is right index of the
sub-array of arr to be sorted */
void mergeSort(int arr[], int l, int r)
{
if (l < r) {
// Same as (l+r)/2, but avoids overflow for
// large l and h
int m = l + (r - l) / 2;
// Sort first and second halves
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);
merge(arr, l, m, r);
}
}
/* UTILITY FUNCTIONS */
/* Function to print an array */
void printArray(int A[], int size)
{
int i;
for (i = 0; i < size; i++)
printf("%d ", A[i]);
printf("\n");
}
/* Driver program to test above functions */
int main()
{
int arr[] = { 12, 11, 13, 5, 6, 7 };
int arr_size = sizeof(arr) / sizeof(arr[0]);
printf("Given array is \n");
printArray(arr, arr_size);
mergeSort(arr, 0, arr_size - 1);
printf("\nSorted array is \n");
printArray(arr, arr_size);
return 0;
}
To something like this:
void mergeSort(int* arr[], int l, int r);
void merge(int* arr[], int l, int m, int r);
I thought it is a simple task because I could simply change every arr to *arr in the functions to dereference them. The program is still runnable but gives me a bunch of unknown numbers.
Then I searched the stack overflow until I see this post:
https://stackoverflow.com/questions/49751409/swapping-2-arrays-in-c#:~:text=Since%20pointer%20is%2064%20bit,two%20int%20which%20get%20swapped.&text=In%20C%20an%20array%20is,they%20are%20pointers%20to%20arrays
It also passes an array by reference. (int* a and int* b)
void swapArray( int *a, int *b, size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
int tmp = a[i];
a[i] = b[i];
b[i] = tmp;
}
}
But in reverse, when I change it to
void swapArray( int a, int b, size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
int tmp = a[i];
a[i] = b[i];
b[i] = tmp;
}
}
It doesn't work, again. Could someone explain to me why and how can I modify my merge sort codes properly? Or where I should look for? I am so confused about this. Any help is appreciated.

int *arr[] is an array of pointers. Or rather it's a pointer to a pointer (it's really int **arr).
To pass a pointer to an array (which almost never is needed) you need e.g. int (*arr) [6]. And yes, the size of the array is then mandatory (variable-length arrays are valid).
But as I said, passning pointers to arrays is almost never needed, because arrays naturally decays to pointers (to their first element).
And as an argument declaration int arr[] is equal to int *arr.
That is, with
void merge(int arr[], int l, int m, int r)
you already pass the array by "reference".

The subscript operator, [ ], has higher precedence than the dereference operator, *. So int *arr[] declares arr to be an array of pointers to int. To make it a pointer to an array, you need int (*arr)[].
Similarly, in expressions, *arr[3] attempts to take element 3 of an array arr and dereference it. Instead you need (*arr)[3] to use *arr to get the array and then [3] to get element 3.

Related

I'm having issues with getting MergeSort to work in C

I'm having issues with getting my mergeSort algorithm to work properly. The code is below, but I'll briefly summarize what I have tried and what I know is not wrong with the code.
The mergeSort function takes a pointer to an array and the array's size as arguments. If the size of the array is less than 2, it returns immediately. I'm sure that this works, because I debugged this part several times. It returns 8 times, which is what I expected it to do.
Next, a variable mid is created as an index to split the array by. I tested it, and I'm pretty confident that mid is correct across all recursions. Then, two arrays are created, the first containing the elements from the indexes 0...mid-1 and the second containing the elements from the indexes mid to n. Next, the sizes of each of these arrays are computed. I tested this too, and the sizes seem correct across all recursions as well. mergeSort is called on the left array and the right array, and then merge is called.
The actual merge function takes a pointer to the original array, a pointer to the left array, a pointer to the right array, and two integer values which are the sizes of each of the left and right arrays. Then, it compares the elements in L and R and copies the smaller of the two into A, in order.
My output, however, is [2] [4] [1] [6] [8] [5] [3] [7]
My expected output is: [1] [2] [3] [4] [5] [6] [7] [8]
I'm genuinely not sure why the code isn't working. There's probably something I'm overlooking, but I've been trying to solve it for an hour and figured I'd ask for help.
If you take the time to answer, or attempt to answer this question, thank you for your time.
My code is below:
#include <stdio.h>
#include <stdlib.h>
void mergeSort(int *, int);
void merge(int *, int *, int, int *, int);
void print(int *, int);
int main() {
int A[8] = { 2, 4, 1, 6, 8, 5, 3, 7 };
int arraySize = sizeof(A) / sizeof(A[0]);
mergeSort(A, arraySize);
print(A, arraySize);
}
void mergeSort(int *A, int n) {
if (n < 2) {
return;
}
int mid = n / 2;
int L[mid];
int R[n - mid];
for (int i = 0; i < mid; i++) {
L[i] = A[i];
}
for (int j = mid; j < n; j++) {
R[j - mid] = A[j + mid + 1];
}
int leftSize = sizeof(L) / sizeof(L[0]);
int rightSize = sizeof(R) / sizeof(R[0]);
mergeSort(L, leftSize);
mergeSort(R, rightSize);
merge(A, L, leftSize, R, rightSize);
}
void merge(int *A, int *L, int leftSize, int *R, int rightSize) {
int i, j, k;
while (i < leftSize && j < rightSize) {
if (L[i] < R[j]) {
A[k] = L[i];
k++;
i++;
} else {
A[k] = R[j];
k++;
j++;
}
}
}
void print(int *A, int n) {
for (int i = 0; i < n; i++) {
printf("[%d] ", A[i]);
}
printf("\n");
}
There are multiple problems:
the intialization loop for R is incorrect: you should copy A[j] instead of A[j + mid + 1]
the merge function should copy the remaining elements from the left or right arrays once the test i < leftSize && j < rightSize fails.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
void mergeSort(int *, int);
void merge(int *, int *, int, int *, int);
void print(const int *, int);
int main() {
int A[8] = { 2, 4, 1, 6, 8, 5, 3, 7 };
int arraySize = sizeof(A) / sizeof(A[0]);
mergeSort(A, arraySize);
print(A, arraySize);
return 0;
}
void mergeSort(int *A, int n) {
if (n < 2) {
return;
}
int mid = n / 2;
int L[mid];
int R[n - mid];
for (int i = 0; i < mid; i++) {
L[i] = A[i];
}
for (int j = mid; j < n; j++) {
R[j - mid] = A[j];
}
int leftSize = sizeof(L) / sizeof(L[0]);
int rightSize = sizeof(R) / sizeof(R[0]);
mergeSort(L, leftSize);
mergeSort(R, rightSize);
merge(A, L, leftSize, R, rightSize);
}
void merge(int *A, int *L, int leftSize, int *R, int rightSize) {
int i, j, k;
while (i < leftSize && j < rightSize) {
if (L[i] <= R[j]) {
A[k++] = L[i++];
} else {
A[k++] = R[j++];
}
}
while (i < leftSize) {
A[k++] = L[i++];
}
while (j < rightSize) {
A[k++] = R[j++];
}
}
void print(const int *A, int n) {
for (int i = 0; i < n; i++) {
printf("[%d] ", A[i]);
}
printf("\n");
}

Need to implement a recursive mergesort code in C using array pointer, its length and a workspace array for the merge function

I need to implement mergesort for arrays up to 100000 integers but the specifications are a bit troublesome: I need to use a pointer to an integer array, its length and an extra workspace array for merging,
The mergesort function should look something like this:
void merge_sort(int *a, int *w, int n)
where a is to be sorted and w is the workspace used for merging, cant use an array and two indexes between what I wanna sort
pseudocode:
merge_sort(int *a, int *w, int n) {
/* take care of stopping condition first */
if the array to be sorted has fewer than two elements then
return
merge_sort( first half of array a);
merge_sort( second half of array a);
merge the two halves of array a into array w
copy array w back into array a
}
merge(int *array, int *workspace, int len) {
initialise indices to point to the beginning of
the left and right halves of array
while there are elements in both halves of array {
compare the elements at the current left and right indices
put the smallest into workspace and increment both the index
it was taken from, and the index in workspace
}
add any remaining elements from left half of array to workspace
add any remaining elements from right half of array to workspace
}
Here is what I got so far:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ARRAY_MAX 100000
void merge_sort(int *a, int *w, int n) {
if (n == 1)
return;
else {
int *temp;
merge_sort(a, w, n / 2);
merge_sort(a + (n / 2), w, (n - (n / 2)));
/** Cannot figure what to pass to merge since it has to be the two halves
and how to copy contents of a to w **/
}
}
void merge(int *a, int *w, int n) {
/** Cannot figure this out **/
}
int main(void) {
int my_array[ARRAY_MAX];
int work_space[ARRAY_MAX];
int count = 0;
int i;
while (count < ARRAY_MAX && 1 == scanf("%d", &my_array[count])) {
count += 1;
}
start = clock();
merge_sort(my_array, workspace, count);
end = clock();
merge_sort(my_array, work_space, count);
for (i = 0; i < count; i++) {
printf("%d\n", my_array[i]);
}
fprintf(stderr, "%d %f \n", count, (end - start) / (double)CLOCKS_PER_SEC);
return EXIT_SUCCESS;
}
The merging phase in function merge_sort iterates on both halves in parallel, taking the smallest element from either side at a time:
void merge_sort(int *a, int *w, int n) {
if (n < 2) {
return;
} else {
int i, j, k;
int n1 = n / 2;
int *b = a + n1;
int n2 = n - n1;
/* sort the left half */
merge_sort(a, w, n1);
/* sort the right half */
merge_sort(b, w, n2);
/* merge the halves into w */
for (i = j = k = 0; i < n1 && j < n2;) {
if (a[i] <= b[j]) {
/* get smallest value from a */
w[k++] = a[i++];
} else {
/* get smallest value from b */
w[k++] = b[j++];
}
}
/* copy remaining elements from a */
while (i < n1) {
w[k++] = a[i++];
}
/* copy remaining elements from b */
while (j < n2) {
w[k++] = b[j++];
}
/* copy sorted elements back to a */
for (i = 0; i < n; i++) {
a[i] = w[i];
}
}
}
The rest of the code has a few issues too:
2 arrays of 100000 ints might exceed the space available for automatic variables.
you sort the array twice
start and end are not defined
Here is a corrected version:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ARRAY_MAX 100000
int main(void) {
int my_array[ARRAY_MAX];
int work_space[ARRAY_MAX];
int i, count;
clock_t start, end;
count = 0;
while (count < ARRAY_MAX && scanf("%d", &my_array[count]) == 1) {
count += 1;
}
start = clock();
merge_sort(my_array, workspace, count);
end = clock();
for (i = 0; i < count; i++) {
printf("%d\n", my_array[i]);
}
fprintf(stderr,"%d %f\n", count, (end - start) / (double)CLOCKS_PER_SEC);
return EXIT_SUCCESS;
}
Remember that in C, when you send an array as an argument to a function, what is really sent is a pointer to the first element. Then you can use that pointer inside the function in a way very similar to an array. So if you are confused about the ”pointers” in the description of (I assume) your homework, perhaps that is the reason?

Quick Sort Array Random Number Generator Nothing Printed Error

I have this C code that creates an array with 100 random numbers and I want to sort it using quick sort, but it always gives a Segmentation fault error.
Here is the code:
#define MAX 100
int a[MAX];
void quick_sort(double *x, int l, int r) {
int l1, r1;
if (l < r) {
l1 = l;
r1 = r;
do {
while (l1 < r && x[l1 - 1] <= x[l - 1]) {
l1++;
}
while (l < r1 && x[r1 - 1] >= x[l - 1]) {
r1--;
}
if (l1 < r1) {
swap(&x[l1 - l], &x[r1 - 1]);
}
} while (l1 < r1);
swap(&x[l - 1], &x[r1 - 1]);
quick_sort(x, l, r1 - 1);
quick_sort(x, r1 + 1, r);
}
}
void printArray(int a[], int size) {
int i;
for (i = 0; i < size; i++)
printf("%d ", a[i]);
printf("\n");
}
int main() {
int i = 1;
int a_size = sizeof(a) / sizeof(a[0]);
srand((unsigned int)time(NULL));
for (i = 0; i < MAX; i++) {
a[i] = rand() % 501;
}
quick_sort(a, 0, a_size);
printArray(a, a_size);
}
The error is that nothing prints when I run the program.
Can someone help me with the problem?
There are many problems in your code:
You do not include <stdio.h>, <stdlib.h>, nor <time.h>.
Your quick_sort function expects a pointer to an array of double, yet you pass an array of int.
The code for function swap() is not posted.
Your implementation of the Quick Sort algorithm in function quick_sort is flawed:
you should not scan slices of size 1, use (r - l > 1).
You cannot use x[l - 1] as pivot, it is not even part of the slice to be sorted. Furthermore, you should extract the pivot from the array before the swapping phase as it may move.
You should not name a variable l, it looks too close to 1 and you do make the mistake here: swap(&x[l1 - l], &x[r1 - 1]);
You should initialize l1 and r1 such that you do not need to subtract 1 in so many places, it leads to confusion and erroneous code.
Study the algorithms from the Wikipedia article and translate one to C.
Here is a corrected version:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 100
void swap(int *a, int *b) {
int x = *a;
*a = *b;
*b = x;
}
// Quick Sort using Hoare's original partition scheme
void quick_sort(int *x, int l, int r) {
if (l < r) {
int pivot = x[l];
int l1 = l - 1;
int r1 = r;
for (;;) {
while (x[++l1] < pivot)
continue;
while (x[--r1] > pivot)
continue;
if (l1 < r1) {
swap(&x[l1], &x[r1]);
} else {
break;
}
}
quick_sort(x, l, r1 + 1);
quick_sort(x, r1 + 1, r);
}
}
void printArray(int a[], int size) {
for (int i = 0; i < size; i++) {
printf("%d ", a[i]);
}
printf("\n");
}
int main(void) {
int a[MAX];
int a_size = sizeof(a) / sizeof(a[0]);
srand((unsigned int)time(NULL));
for (int i = 0; i < MAX; i++) {
a[i] = rand() % 501;
}
quick_sort(a, 0, a_size);
printArray(a, a_size);
return 0;
}

Sort elements in array C [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am trying to create a program that will sort elements in 4 steps (read elements - print elements - sort them - print the sorted version).
I need help with the sorting (third) part.
Here is my code:
/*
* A simple program to sort numbers in correct order
*/
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
#define SENTINEL -99
int main()
{
int tableFill(int a[], int max);
void tableInsert(int a[], int num, int val);
void tableSort(int a, int n);
void tablePrint(int a, int n);
int num;
int table[MAXSIZE];
int max;
num=tableFill(table,MAXSIZE);
return EXIT_SUCCESS;
}
int tableFill(int a[], int max)
{
int r; // input from scanf
int next; // score from user
int cnt = 0;
printf("Enter the numbers! \n");
while ((r=scanf("%i", &next))!= EOF && cnt<max)
{
if (r == 0) //invalid input data
{
printf("Nonnumeric data entered. Please enter a number. \n");
while (getchar()!= '\n'); // flush invalid data
}
else
a[cnt++]=next;
}
if(r==1) //another value was read but the array is full
printf("Error - too many values. Array size %i.\n", max);
}
void tableInsert (int a[], int num, int val)
{
int pos;
for(pos = num; pos>0 && val<a [pos-1]; pos--)
a [pos] = a [pos -1];
a[pos] = val;
}
void tableSort(int a, int n)
{
}
void tablePrint(int a, int n)
{
int i;
for(i = n -1; i>=0; i++)
{
printf("%i\n",a[i]);
}
}
SOLUTION
I used David C. Rankin's solution and fixed my code. This is my final version:
/*
* A simple program to sort numbers in the correct order
*/
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10 //max elements in array
int main () {
int tableFill (int a[], int max);
void tableSort (int a[], int n);
void tablePrint (const a[], int n);
int arr[MAXSIZE]; //creating an array
int n = tableFill (arr, MAXSIZE); //declaring variable to work with array
tablePrint (arr, n); //prints unsorted values
printf ("Here is your sorted array:\n");
tableSort (arr, n); // sorts values in order
tablePrint (arr, n); // prints sorted values
return 0;
}
// read values from stdin into array up to 'max' values
int tableFill(int a[], int max) {
int r; // input from scanf
int next; // score from user
int cnt = 0; // loop variable
printf("Enter the numbers! \n");
while ((r=scanf("%i", &next))!= EOF && cnt<max)
{
if (r == 0) //invalid input data
{
printf("Nonnumeric data entered. Please enter a number. \n");
while (getchar()!= '\n'); // flush invalid data
}
else
a[cnt++]=next;
}
if(r==1) //another value was read but the array is full
printf("Error - too many values. Array size %i.\n", max);
return cnt;
}
// swap values at array indexes 'i' and 'j'.
void tableSwap (int a[], int i, int min_index)
{
int tmp = a[i];
a[i] = a[min_index];
a[min_index] = tmp;
}
//sort array
void tableSort (int a[], int n)
{
void tableSwap (int a[], int i, int min_index);
int i, j; //loop counters
int min, min_index; //adjusting variables for loops
for (i = 0; i <= n - 2; i++) {
min = a[i];
min_index = i;
for (j = i + 1; j <= n - 1; j++) {
if (a[j] < min){
min = a[j];
min_index = j;
}
}
tableSwap (a, i, min_index);
}
}
//print all elements in array.
void tablePrint (const a[], int n)
{
int i; //variable for print
for (i = 0; i < n; i++)
printf ("%d ", a[i]);
printf ("\n");
}
As pointed out in the comments, qsort is the defacto standard sort routine contained in the C standard library. It is incredibly flexible and incredibly fast due to using a combination of sorting methods optimized for the range of data being sorted. Beginning C users generally have difficulty writing the compare functions because it involves the use of pointers. Just take the time needed to write a few compare functions are get comfortable with it -- it will save you a lot of grief in the long run.
That said, before looking at both alternative sorts, C-style generally uses lower-case for variable and function names. Leave camelCase names for C++. See e.g. NASA - C Style Guide, 1994
Sorting with the old-slow bubblesort. For sorting anything with greater than 100 elements, the efficiency of the bubblesort craters. It is hundreds of times slower than qsort for any large number of element. That being said, putting a bubblesort together that incorporates your tableswap requirement is straightforward:
/** sort array using slow old bubblesort */
void tablebubblesort (int *a, int n)
{
int i, j;
for (i = 0; i < n - 1; i++) {
for (j = 0; j < n - i - 1; j++) {
if (a[j] > a[j + 1]) /* For decreasing order use < */
tableswap (a, n, j, j+1);
}
}
}
Your tableswap function will look similar to:
/** swap values at array indexes 'i' and 'j'. */
void tableswap (int *a, int n, int i, int j)
{
if (i >= n || j >= n) return;
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
Simply call the function in your code with tablebubblesort (arr, n);
qsort is even simpler. The full function (you really don't need a separate function) is:
/** qsort the array */
void tablesort (int *a, int n, size_t sz)
{
qsort (a, n, sz, compare);
}
It requires a compare function which is simply:
/** qsort compare function */
int compare (const void *a, const void *b)
{
return (*(int *)a - *(int *)b);
}
Don't let you eyes roll over in your head simply because you see const void *a, etc.. it is really straight forward. Your a and b pointers represent a pointer to individual integers in the array (e.g if say a[1] = 5, the pointer is just &a[1] the address of the element). So taking the compare function apart, knowing you are just passing the address of an element (e.g. integer pointers) to compare, you would write it long-hand as follows:
int compare (const void *a, const void *b)
{
int *value1 = (int *)a; /* cast each to int pointer */
int *value2 = (int *)b;
if (*value1 > *value2) /* compare dereferenced values */
return 1;
if (*value1 < *value2)
return -1;
return 0;
}
Or, if it makes you happier, you can cast and dereference all at once and then just operate on integer values:
int compare (const void *a, const void *b)
{
int value1 = *(int *)a;
int value2 = *(int *)b;
if (value1 > value2)
return 1;
if (value1 < value2)
return -1;
return 0;
}
Either way it is the same. (arguably, the first is the most proper because it avoid the "appearance" of type punning pointers and derefencing void values, but that is for another day) There is no magic, just do it enough times for integers, strings, structs, etc.. until it sinks in. It's more than worth the time.
Putting the rest of the pieces together, you could meet your requirements with something similar to the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXI 128
int tablefill (int *a, int max);
void tableinsert (int *a, int *n, int max, int num, int val);
void tableswap (int *a, int n, int i, int j);
void tablesort (int *a, int n, size_t sz);
void tablebubblesort (int *a, int n);
void tableprint (int *a, int n);
int compare (const void *a, const void *b);
int main (void) {
int arr[MAXI] = {0};
int n = 0;
printf ("enter array values ([ctrl+d] to end)\n");
n = tablefill (arr, MAXI);
tableprint (arr, n);
printf ("\ninsert '5' as the '2nd' element of array\n");
tableinsert (arr, &n, MAXI, 2, 5);
tableprint (arr, n);
printf ("\nswap indexes '1' and '3'\n");
tableswap (arr, n, 1, 3);
tableprint (arr, n);
printf ("\nsorted array\n");
#ifdef WQSORT
tablesort (arr, n, sizeof *arr); /* gcc -DWQSORT to use tablesort */
#else
tablebubblesort (arr, n);
#endif
tableprint (arr, n);
return 0;
}
/** read values from stdin into array up to 'max' values. */
int tablefill (int *a, int max)
{
int idx = 0, tmp;
while (idx + 1 < max && scanf ("%d", &tmp) == 1)
a[idx++] = tmp;
return idx;
}
/** insert 'val' as the 'num' element in 'a' ('num - 1' index),
* update 'n' to current number of elements.
*/
void tableinsert (int *a, int *n, int max, int num, int val)
{
if (num >= max || *n + 1 == max) return;
if (num >= *n) { a[num] = val; (*n)++; return; }
int i;
for (i = *n; i >= num; i--)
a[i] = a[i-1];
a[i] = val;
(*n)++;
}
/** swap values at array indexes 'i' and 'j'. */
void tableswap (int *a, int n, int i, int j)
{
if (i >= n || j >= n) return;
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
/** qsort the array */
void tablesort (int *a, int n, size_t sz)
{
qsort (a, n, sz, compare);
}
/** sort array using slow old bubblesort */
void tablebubblesort (int *a, int n)
{
int i, j;
for (i = 0; i < n - 1; i++) {
for (j = 0; j < n - i - 1; j++) {
if (a[j] > a[j + 1]) /* For decreasing order use < */
tableswap (a, n, j, j+1);
}
}
}
/** print all elements in array. */
void tableprint (int *a, int n)
{
if (!a) return;
int i;
for (i = 0; i < n; i++)
printf (" a[%2d] : %d\n", i, a[i]);
}
/** qsort compare function */
int compare (const void *a, const void *b)
{
return (*(int *)a - *(int *)b);
}
The code contains both the bubblesort and qsort version of the sort. You simply pass the define -DWQSORT to compile with the qsort code or compile without it for the bubblesort. e.g.
Compile Both Versions
$ gcc -Wall -Wextra -Ofast -o bin/array_fill array_fill.c
$ gcc -Wall -Wextra -Ofast -DWQSORT -o bin/array_fill_qsort array_fill.c
Example Use/Output
$ echo "1 4 2 3" | ./bin/array_fill
enter array values ([ctrl+d] to end)
a[ 0] : 1
a[ 1] : 4
a[ 2] : 2
a[ 3] : 3
insert '5' as the '2nd' element of array
a[ 0] : 1
a[ 1] : 5
a[ 2] : 4
a[ 3] : 2
a[ 4] : 3
swap indexes '1' and '3'
a[ 0] : 1
a[ 1] : 2
a[ 2] : 4
a[ 3] : 5
a[ 4] : 3
sorted array
a[ 0] : 1
a[ 1] : 2
a[ 2] : 3
a[ 3] : 4
a[ 4] : 5
$ echo "1 4 2 3" | ./bin/array_fill_qsort
<same outoput>
Look over all the code and let me know if you have questions. This is basic meat and potatoes C and you need to make sure you understand each line, and each character in each line. Take it slow.
Regarding
int tableFill(int a[], int max);
void tableInsert(int a[], int num, int val);
void tableSort(int a, int n);
void tablePrint(int a, int n);
You're declaring the prototypes inside main which is not usually done. They are usually declared in global scope so that they stay put till the end.
Regarding
int tableFill(int a[], int max)
You're not returning anything. Since you're dealing with the pointers you could change int to void.
Regarding
void tableInsert (int a[], int num, int val)
Ask yourself from where you are calling this function.
Regarding
void tableSort(int a, int n)
{
}
See this guide which explains sorts.
Regarding :
void tablePrint(int a, int n)
{
int i;
for(i = n -1; i>=0; i++)
{
printf("%i\n",a[i]);
}
}
Since you're printing an array,so one parameter to this function should be an array.

Double pointer to traverse and find 5 max elem in 2D array. C

So am trying to do a question that aims to find 5 max elements in int 2D array.
I had no issues with dynamically allocating the array and inputting the elements into it.
printf("Your 2-d order of choice?\n");
scanf ("%d %d", &i ,&j);
int array[i][j];
//Taking 2d array input
for (int c = 0; c < i; c++)
{
for (int d = 0; d < j; d++)
{
scanf("%d", &array[c][d]);
}
}
However, to find the 5 max elements and store them in an array it asks for a function with prototype.
int * max5(int **, int ,int)
I don’t know how to use double pointer to traverse the 2D array, even though I read a few other posts regarding int**, and what will int* (return type) exactly be and how to incorporate it.
There are the many ways to pass array as pointers
As per you said that if you take array like int array[10][10];.
Using single pointer you can do like
int *arr = max5 ((int *)array, 10, 10);
And traverse array as
int * max5 (int *arr, int m, int n)
{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d ", *((arr+i*n) + j));
//.........
}
OR using double pointer you can also do like
int *arr = max5 ((int **)array, 10, 10);
And traverse like
int * max5 (int **arr, int m, int n)// Same as int * max5 (int *arr[], int m, int n)
{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d ", *((arr+i*n) + j));
//.........
}
Now other way also possible it just for your information
From C99, C language supports variable sized arrays to be passed simply by specifying the variable dimensions.
int *arr = max5 (array, 10, 10);
And traverse like
int * max5 (int arr[][10],int m,int n) //Same as int * max5 ( int (*arr)[10], int m,int n))
{
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
printf("%d ", arr[i][j]);
//.........
}
This is the max5 function.
It gets 5 elements in res (allocated by malloc), then for the remaining elements of a, it finds the smallest elements of res and compare it with that a element - if the res element is maller than the a element, that res element is replaced with the a one.
Note that I wouldn't usually use a magic number (5) in the function, but since it's called max5 ..
#include <limits.h>
int *max5(int **a, int rows, int cols) {
int *res = malloc(5 * sizeof(int));
int i,j,k,n=0; // n, number of elements in res
for (i=0 ; i<rows ; i++) {
for (j=0 ; j<cols ; j++) {
if (n < 5) res[n++] = a[i][j];
else {
// find lowest res element
int lowest=0;
for(k=1 ; k<5 ; k++) { // start from 1!
if (res[k] < res[lowest]) {
lowest = k;
}
}
// if lowest res is < a[i][j], replace it
if (res[lowest] < a[i][j]) res[lowest] = a[i][j];
}
}
}
return res;
}
For the sake of demo, this is not optimized (looking for the min all the time). One way would be to sort the res array after 5 elements have been inserted, and after one of its element is replaced (which should statistically happen less and less over the iterations). Another way would be to build a tree when the elements are input initially.
As mentioned by #haccks, array is to be declared as a int **, then i rows must be int * allocated (ie, i pointers to int), then each of the row is to be allocated the size of j int.
With the given prototype, you have to declare array as int ** and dynamically allocate memory to it.
int **array = malloc(i*sizeof(int*));
for(int row = 0; row < i; row++)
array[row] = malloc(j*sizeof(int));
Now you can call your max5 function as
int *a = max5(array, i, j);
Then dynamically allocate an array inside max5 and return it from max5.

Resources