Using array from main in function ( C ) - c

is there any way to use static array, defined in main(), in another function, without giving it to the function as a parameter?
For example:
main() has defined array:
int Array[10];
filled with integers. I'd like to create a comparing function for qsort, that has to have this header:
int compar (const void* a, const void* b);
and I would like it to decide like this:
if Array[a]<Array[b] return 1
etc...
This array cannot be given to qsort directly, but is required for exact sorting.
Also, this array has to be static (no reallocing).
Does anyone have any ideas?

The only way is, of course, so make the address of the array available as a global variable.
This is possible even if the array itself is inside main(), but you have to initialize the global to the properly scoped address, and watch the life-time, of course.
int *mains_array;
static int qsort_callback(const void *a, const void *b)
{
/* use mains_array */
}
int main(void)
{
int secret_array[100];
mains_array = secret_array;
qsort(something, something, qsort_callback);
}
It's a pretty ugly solution, it should be given more thought.

You can't access a local variable from another function. You need to make it global or file scoped.
Global:
/* Declare Array outside any function */
int Array[10];
int main(...
or, file scoped:
/* Declare Array outside any function */
static int Array[10];
int main(...
Note:
Your compare function will receive pointers to the elements to compare. If you are sorting an array of int you need to dereference the pointer in your compare function:
I'm assuming that Array isn't the array you want to sort, but an array that contains information on how to sort an array.
int compare (const void * ap, const void * bp)
{
int a = *((int*)ap);
int b = *((int*)bp);
if (Array[a] < Array[b]) {
return 1;
}
if (Array[a] > Array[b]) {
return -1;
}
return 0;
}

qsort requires the address of the array, so you don't have a choice. But where is defined the array, that does not matter. You just need to be able to refer to it.
The qsort signature is:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
So you will call it by:
qsort(Array, 10, sizeof(int), compar);
And you'll do the compare function as usual:
int compar (const void* a, const void* b) {
return *((int*)a) - *((int*)b);
}
You need to understand that the values passed to compar are not the indexes but the address of the cells of your array. So you don't have to use Array from the compar function, you already have what you need.

You're already giving him your array by calling
qsort (a, numberOfElements, sizeOfEachElement, compare);
What you need to do in your compare function is this:
int compare (const void * a, const void * b)
{
//Here int can be other type
return ( *(int*)a - *(int*)b );
}

Related

Function with parameters but no arguments

I was reading a mergeSort from standard library in c and found that it has a compare function as an argument(i.e void msort(void *base, size_t nitems, size_t size, int (*compar)(const void , const void)) when it's defined). However, in actual use when the msort function is called, compar function didn't have an argument passed to it(even though it had two parameters, which are (const void *, const void *) as parameters. look the ff code snippet and I would appreciate how it's possible for a function with parameters to be used without arguments in the time it's called??
#include <stdio.h>
#include <stdlib.h>
int values[] = { 88, 56, 100, 2, 25 };
int cmpfunc (const void * a, const void * b) {
return ( *(int*)a - *(int*)b );
}
int main () {
int n;
printf("Before sorting the list is: \n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
msort(values, 5, sizeof(int), cmpfunc);
printf("\nAfter sorting the list is: \n");
for( n = 0 ; n < 5; n++ ) {
printf("%d ", values[n]);
}
return(0);
}
This is a so called a function pointer: you're basically passing the function cmpfunc() as a parameter, which will then be used by the msort() function internally, with the proper arguments.
A function pointer is a variable that stores the address of a function that can later be called through that function pointer. This is useful because functions encapsulate behavior.
Function pointers are the precursors of function closures.
To be more clear: the reason why it has no arguments is because you don't know them yet.
Let me explain: cmpfunc() serves to compare 2 elements and tell which one precedes the other. But msort() will need to do many different comparisons, since it has to iterate over all the elements of values[]. Therefore, internally msort() is going to select 2 elements at a time, let's call them x and y, compare them cmpfunc(x, y) and swap them if needed.
void msort(void *base, size_t nitems, size_t size, int (*compar)(const void* , const void*))
The function msort takes a function pointer as its final argument. Just like regular paramters, this parameter tells the msort function that "an address of a function which itself takes two const void* as an argument and retuns an int" will be passed as a parameter. When called like:
msort(values, 5, sizeof(int), cmpfunc);
without the paranthesis at the end of cmpfunc, you are just passing the address of cmpfunc and not actually calling it, therefore it doesn't make sense to pass parameters anyway. You are merely telling the msort where to find the function.
Who actually calls the cmpfunc is the msort. If you have access to its source, you probably can see when and how it calls it (with appropriate parameters passed).
I won't repeat what others have correctly described about "passing the address of a function as a parameter to another function."
A "use case" may help you understand "WHY?"
From your example:
int cmpAscending (const void * a, const void * b) {
return ( *(int*)a - *(int*)b );
}
Now, a "twin" of that:
int cmpDescending (const void * a, const void * b) {
return ( *(int*)b - *(int*)a ); // NB: subtle difference
}
Now, a program can pass the address of the appropriate compare function to msort().
if( ascending )
msort( values, 5, sizeof(int), cmpAscending );
else
msort( values, 5, sizeof(int), cmpDescending );
There are even more economical ways to achieve this:
msort( values, 5, sizeof(int), ascending ? cmpAscending : cmpDescending );
An example, in the main function, foo receives the address of the bar function. Then function foo can call function bar via the function pointer pbar that it received as an argument:
#include <stdio.h>
void bar(int x )
{
printf("%d\n", x);
}
void foo(void(*pbar)(int))
{
pbar(10);
pbar(20);
}
int main(void)
{
foo(bar);
return(0);
}

How to implement suffix array in C without using qsort?

I searched for the implementation of suffix array in C, but all the programs I saw were in C++ which used sort. I am not sure how can I use the built-in function of C, qsort() in place of sort() function of C.
Can we implement suffix arrays without using qsort()?
or
how to use qsort() to implement suffix arrays in C?
here is the code that I got from geeksforgeeks.com:
int cmp(struct suffix a, struct suffix b)
{
return strcmp(a.suff, b.suff) < 0? 1 : 0;
}
int *buildSuffixArray(char *txt, int n)
{
// A structure to store suffixes and their indexes
struct suffix suffixes[n];
// Store suffixes and their indexes in an array of structures.
// The structure is needed to sort the suffixes alphabatically
// and maintain their old indexes while sorting
for (int i = 0; i < n; i++)
{
suffixes[i].index = i;
suffixes[i].suff = (txt+i);
}
// Sort the suffixes using the comparison function
// defined above.
sort(suffixes, suffixes+n, cmp);
// Store indexes of all sorted suffixes in the suffix array
int *suffixArr = new int[n];
for (int i = 0; i < n; i++)
suffixArr[i] = suffixes[i].index;
// Return the suffix array
return suffixArr;
}
the cmp function is comparing structure data type while I am getting an error when using qsort(), which says that only void input is allowed.
The declaration of the qsort function is as follows:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
You'll notice that the comparison function it accepts must be defined to take a const void * for each of its two parameters, but you're instead passing in a struct suffix for each one.
You need to change your comparison function to use the parameter types that qsort expects. Then you can convert those parameters inside of the function to the proper pointer type and use those.
int cmp(const void *p1, const void *p2)
{
const struct suffix *a = p1;
const struct suffix *b = p2;
return strcmp(a->suff, b->suff) < 0? 1 : 0;
}

Initializing arrays and structures in a function

I am trying to initialize an array of elements to a finite value in a c function.
one way i know is to use a for loop to initialize those values but I am wondering if there is a simple way? I know that they can be initialized during array declaration though but I wouldn't prefer that way.
ex:
int a[10];
void foo(void)
{
for (int i=0; i<10;i++)
{
a[i] = 10;
}
}
Thanks
For the special case, that it is an char/byte array you could use the memset function:
#include <string.h>
void * memset ( void * ptr, int value, size_t num );
Attention: Thoug an 'int' is passed to memset, the ptr will increase in char/byte steps. So it is not suitable for an int array!
But you could use memfill:
#include <publib.h>
void *memfill(void *buf, size_t size, const void *pat, size_t patsize);
See http://manpages.ubuntu.com/manpages/saucy/man3/memfill.3pub.html for details. But it is probably not everywhere available.

qsort() can't understand the detail in C

Why when we use qsort(), int(*compar)(const void*,const void*) haven't add any paraments in, but can also do their functions?
Such as this :
double vals[NUM];
qsort(vals,NUM,sizeof(double),mycomp);
When you append parenthesis to the identifier representing a function, with a list of parameters between, you're calling the function.
In this case, you don't want to call the function, however. You want qsort to call the function to determine whether or not one element is larger or smaller than the other.
It seems you are asking about function pointers in general.
Here is a simple example of function pointer:
int compare(int i, int j)
{
return i > j ? i : j;
}
void process(int i, int j, int(*pfunc)(int, int))
{
printf("%d\n", pfunc(i, j));
}
int main(void)
{
process(1, 2, compare);
return 0;
}
In this example process is sort of like qsort, while compare is the function which we define ourselves. We need to tell qsort how to compare data, but we can't access qsort directly, so pass our own function to it which tells qsort how to compare.
qsort is generic. It doesn't know what type of data it is processing, so it can't simply compare elements using <. What it does instead is let you, the programmer, give it a function to use to compare elements. So, yes you do care about how mycomp works, you need to define it.
int mycomp(const void *a, const void *b) {
const double *lhs = a;
const double *rhs = b;
if (*lhs < *rhs) return -1;
if (*lhs > *rhs) return 1;
return 0;
}
inside of qsort, every time it needs to compare two elements it will pass them to your mycomp function and examine the result. If you define it wrong, your array will be incorrectly arranged (unsorted).

const array const {}

So you can do this:
void foo(const int * const pIntArray, const unsigned int size);
Which says that the pointer coming is read-only and the integer's it is pointing to are read-only.
You can access this inside the function like so:
blah = pIntArray[0]
You can also do the following declaration:
void foo(const int intArray[], const unsigned int size);
It is pretty much the same but you could do this:
intArray = &intArray[1];
Can I write:
void foo(const int const intArray[], const unsigned int size);
Is that correct?
No, your last variant is not correct. What you are trying to do is achieved in C99 by the following new syntax
void foo(const int intArray[const], const unsigned int size);
which is equivalent to
void foo(const int *const intArray, const unsigned int size);
That [const] syntax is specific to C99. It is not valid in C89/90.
Keep in mind that some people consider top-level cv-qualifiers on function parameters "useless", since they qualify a copy of the actual argument. I don't consider them useless at all, but personally I don't encounter too many reasons to use them in real life.
Use cdecl. It gives an error on the second entry. The first only clearly suggests that the second const refers to the *.
In C/C++, you cannot pass an entire array as an argument to a function.
You can,
however, pass to the function a pointer to an array by specifying the array's name
without an index.
(E.g)
This program fragment passes the address of i to func1() :
int main(void)
{
int i[10];
func1(i);
.
.
.
}
To receive i, a function called func1() can be defined as
void func1(int x[]) /* unsized array */
{
.
.
}
or
void func1(int *x) /* pointer */
{
.
.
}
or
void func1(int x[10]) /* sized array */
{
.
.
}
source : THE COMPLETE REFERENCE - HERBERT.

Resources