Passing inputs to a function from a list of inputs without hard-coding it in C - c

Suppose I have a function:
void add(int a, int b , int c);
and I have an array which contains 3 integer values:
int L[] = {1,2,3};
Now I want to pass these values to add without writing add(L[0],L[1],L[2]).
I mean is there a way of creating a Single input from multiple inputs and passing it to the function which will treat that single input as multiple inputs ??.

You could try this
int L[] = {1,2,3};
add(L, 3);
where
void add(int *x, int length)
{
// use x[0], x[1], etc.
}
But I am not sure why you are having problem with your current approach.
Another option would probably be to encapsulate those three integers into a structure and pass the structure along.

If you mean something like Python
def foo(a, b, c):
return a + b + c
x = (1, 2, 3)
print(foo(*x)) # the '*' does the magic of calling foo with 1, 2, 3
then this is not possible in portable C.
What you can do is change the interface of foo to accept an array of arguments, e.g.
int sum(int *data, int n) {
int tot = 0;
for (int i=0; i<n; i++) {
tot += data[i];
}
return tot;
}
can call it with
int x[] = {10, 20, 30, 40};
int res = sum(x, 4);
If you cannot change the function definitions and you have many of them with the same signature what you can do is use function pointers to factor out the call:
int sum3(int a, int b, int c) {
return a+b+c;
}
int mul3(int a, int b, int c) {
return a*b*c;
}
int call_int_int3(int(*f)(int, int, int), int* args) {
return f(args[0], args[1], args[2]);
}
...
int data[] = {10, 20, 30};
int sum = call_int_int3(sum3, data);
int prod = call_int_int3(mul3, data);
but you will need a different wrapper for each distinct signature (number and type of arguments and type of return value).

Related

How to use the sort function in C programming

Hello guys i have a situation here am trying to sort out numbers in C language but i seem to struggle to put a sort function can you please help me with this following souce code that prints out number and supose to sort them but i cant...please help:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num1 = 8, num2 = 6, num3 = 2, num4 = 4, num5 = 1;
printf("%d %d %d %d %d", num1, num2, num3, num4, num5);
// qsort(); THIS IS WHAT I STRUGGLE WITH AT THE MOMENT
return 0;
} // THIS CODE PRINTS OUT NUMBERS BUT ARE NOT SORTED...SO I NEED TO SORT THEM PLEASE
// YOUR HELP WILL BE MUCH APPRECIATED
// I NEED TO KNOW HOW TO USE THE SORT(qsort) FUNCTION
qsort() does one thing and it does it exceptionally well, it sorts arrays, and does so very efficiently. As noted in the comments, before you can use qsort() you will need to collect your values in an array rather than separate variables. Once you have an array, using qsort() is trivial, your only responsibility using qsort is to write the compare() function.
New users of qsort() usually have their eyes roll back in their heads when they see the declaration for the function:
int compare (const void *a, const void *b) { ... }
It's actually quite simple. a and b are simply pointers to elements of the array to compare. Since qsort() can handle any type array, the parameter type are void pointers. If you have an array of int, a and b are just pointers int (e.g. int*). You simply need to write your compare function to cast a and b to int* and dereference to compare the int values with each other.
The return of compare() is either less than zero (a sorts before b), zero (a and b are equal) or greater than zero (b sorts before a). So a niave compare() can be as simple as:
int compare (const void *a, const void *b)
{
int x = *(int *)a,
y = *(int *)b;
return x - y;
}
However, there is always a potential for x - y to overflow with a large negative x and large y or large x and large negative y. So you generally try and use the differnce between two comparisons to eliminate the potential for overflow, e.g.
int compare (const void *a, const void *b)
{
int x = *(int *)a,
y = *(int *)b;
return (x > y) - (x < y);
}
Now if you take any value of a and b the return will either be -1, 0 or 1 providing the sort information for qsort() without chance of overflow.
A short example using your values could be written as:
#include <stdio.h>
#include <stdlib.h>
int compare (const void *a, const void *b)
{
int x = *(int *)a,
y = *(int *)b;
return (x > y) - (x < y);
}
void prn_arr (int *arr, size_t nmemb)
{
for (size_t i = 0; i < nmemb; i++)
printf (i ? ", %d" : "%d", arr[i]);
putchar ('\n');
}
int main()
{
int num[] = {8, 6, 2, 4, 1};
size_t nmemb = sizeof num / sizeof *num;
puts ("array before sort:\n");
prn_arr (num, nmemb);
qsort (num, nmemb, sizeof *num, compare);
puts ("\narray after sort:\n");
prn_arr (num, nmemb);
}
Example Use/Output
$ ./bin/qsortnum
array before sort:
8, 6, 2, 4, 1
array after sort:
1, 2, 4, 6, 8
Look things over and let me know if you have further questions.

why pass as argument of a function a function?

i have a little question.
i'm studying C with devc++ (as start) and i have seen as argument function you can pass a function, this is ok but why?
for example u can write as argument:
void myfunc(void(*func)(int)){}
but if u simple call function with his name and argument it is not better?
like example:
void myfunction (){name of func to call(myargs); }
there's a difference?
it seems the same thing but with more simple and short code
edit:
i want only know
void map (int (*fun) (int),int x[ ], int l) {
for(i = 0; i < l; i++)
x[i] = fun(x[i]);
}
why u use this instead of:
void map (int x[ ], int l) {
for(i = 0; i < l; i++)
x[i] = nameoffunction(yourargument);
}
You can use a function pointer as a parameter if you want your function to do different things depending on what the user wants.
Here's a simple example:
#include <stdio.h>
int add(int x, int y)
{
return x + y;
}
int subtract(int x, int y)
{
return x - y;
}
int multiply(int x, int y)
{
return x * y;
}
int divide(int x, int y)
{
return x / y;
}
int operation(int x, int y, int (*func)(int, int))
{
printf(" x=%d, y=%d\n", x, y);
return func(x,y);
}
int main()
{
int x = 8, y = 4;
printf("x+y=%d\n", operation(x,y,add));
printf("x-y=%d\n", operation(x,y,subtract));
printf("x*y=%d\n", operation(x,y,multiply));
printf("x/y=%d\n", operation(x,y,divide));
return 0;
}
A very good example is the classic sorting function qsort. It's a library function, which means that you only have access to it's prototype. In order to make qsort general, you have to write your own compare function. A typical implementation looks like this for regular integers:
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
And then, if you have an array arr of integers you can sort it with qsort(arr, sizeof(arr), cmpfunc)
You might ask why this is not built in the qsort function? After all, it would be easy to make it work for both floats and integers. Yes, but imagine if you have an array of structs that look like this:
struct {
char *firstname;
char *lastname;
int age;
} persons[10];
How would you sort this? Well, that's not obvious. You might want all three. In that case, write three different compare functions.
i want only know
void map (int (*fun) (int),int x[ ], int l) {
for(i = 0; i < l; i++)
x[i] = fun(x[i]);
}
why u use this instead of:
void map (int x[ ], int l) {
for(i = 0; i < l; i++)
x[i] = nameoffunction(yourargument);
}
Let's answer the question with a question - what if you want to perform more than one type of mapping? What if you want to map both x2 and √x?
You could certainly do something like
void map( int x[], int l, int type )
{
for ( int i = 0; i < l; i++ )
{
if ( type == MAP_SQUARED )
x[i] = int_square( x );
else if ( type == MAP_ROOT )
x[i] = int_root( x );
...
}
}
which works, but is hard to read and cumbersome to maintain - every time you want to perform a new mapping, you have to add a new case to the map function.
Compare that to
void map( int x[], int l, int (*fun)(int) )
{
for ( int i = 0; i < l; i++ )
x[i] = fun( x[i] );
}
...
map( x, l, int_square );
map( y, l, int_root );
You don't have to hack the map function to get different mappings - you only have to pass the function that operates on the individual elements. If you want to perform a new mapping, all you have to do is write a new function - you don't have to edit the map function at all.
The C standard library uses this form of delegation in several places, including the qsort function (allowing you to sort arrays of any type in any order) and the signal function (allowing you to change how a program reacts to interrupts dynamically).

Pointer to multidimensional array error: Expression must have pointer-to-object type

The following code returns the error: Expression must have pointer-to-object
type. somehow the problem lies in the way I reference the parameters A, B and out which each point to a 2D array. Any help would be much appreciated.
The goal is to multiply two arrays.
#include <stdio.h>
void matrixmul(const float *A, const float *B, int m, int n, int k, float *out)
{
float value = 0.0;
int x, y, z;
for (x = 0; x < k; x++) {
for (y = 0; y < m; y++) {
for (z = 0; z < n; z++) {
float product = A[y][z] * B[z][y];
value = value + product;
printf("%lf", value);
}
out[y][x] = value;
value = 0;
}
}
}
int main(void) {
float a[2][3] = {
{ 1.0,2.0,1.0 },
{ 3.0,4.0,1.0 }
};
float b[3][1] = {1, 2, 3};
float array[2][1];
matrixmul((float *) a, (float *) b, 2, 3, 1, (float *) array);
return 0;
}
Since A is declared as const float *A in the function, A[y][z] is an invalid term. A[y] evaluates to type const float. You can't use an array operator, [z], with a float.
The same problem occurs with B and out.
You can define the function as
void matrixmul(const float A[][3], const float B[][1], int m, int n, int k, float out[][1])
{
...
}
and call the function simply as:
matrixmul(a, b, 2, 3, 1, array);
C99/C11 support variable length arrays. Assuming you can use compiler that supports C99/C11, you can define the function as
void matrixmul(int arows, int acols, int bcols,
const float A[arows][acols],
const float B[acols][bcols],
float out[arows][bcols])
{
...
}
and call the function using
matrixmul(2, 3, 1, a, b, array);
The function does not know the dimensions of your array, so it does not know how to calculate the address of a value given the row and column. You can use a function's arguments to define the dimensions of your matrix, however. You will have to rearrange the arguments in your function such that the arguments specifying the dimensions appear before the array. Using your function, it might look something like this:
void matrixmul(int m, int n, int k, const float A[m][n], const float B[n][m], float out[m][k])
By the way, I haven't really read fully through the function, but is out[y][k] = value; supposed to be out[y][x] = value;?

How to swap 2 numeric numbers of unknown exact type, via two void pointer parameters?

I need to write a function that replaces 2 "numeric numbers", of otherwise unknown type.
I don't know the exact type and I can only use 2 parameters.
So this is what I have tried:
void swap(void *p1, void *p2)
{
char p;
char * q1 = (char *)p1;
char * q2 = (char *)p2;
for (int i = 0; i < sizeof(long double); i++)
{
p = q1[i];
q1[i] = q2[i];
q2[i] = p;
}
}
Usage:
double a = 100123000000.2;
double b = 100065450000.3;
printf("a: %1f, b: %1f\n", a, b);
swap(&a, &b)
printf("a: %1f, b: %1f\n", a, b);
This works fine but my question is what if my number is bigger then long double (or there is no one..)
Is my solution OK?
This works fine but my question is what if my number is bigger (?)
Is my solution is OK ?
Code will have trouble unless it knows the exact size. So, no, OP's solution is not OK.
Somehow void swap() needs to know the size of the data to swap.
i can only use 2 parameters.
Code can cheat and put all the data into 1 argument as a compound literal, since C99.
typedef struct {
void *a;
void *b;
size_t sz;
} swap_T;
// Only 1 parameter!!
void swap(swap_T sw) {
unsigned char * q1 = sw.a;
unsigned char * q2 = sw.b;
while (sw.sz > 0) {
sw.sz--;
unsigned char p = q1[sw.sz];
q1[sw.sz] = q2[sw.sz];
q2[sw.sz] = p;
}
}
int main(void) {
double a = 100123000000.2;
double b = 100065450000.3;
printf("a: %g, b: %g\n", a, b);
swap(((swap_T ) { &a, &b, sizeof a } )); // Compound literal
printf("a: %g, b: %g\n", a, b);
return 0;
}
Output
a: 1.00123e+11, b: 1.00065e+11
a: 1.00065e+11, b: 1.00123e+11
Code could wrap the swap(((swap_T ) { &a, &b, sizeof a } )) in a macro that looks like a function call of 2
#define SWAP(a,b) (swap(((swap_T ) { &(a), &(b), sizeof (a) } )))
...
SWAP(a,b);
As long as a is not an expression with a variable logic array (VLA) and with side-effects, the macro should work fine.
Of course, best if a,b are the same type.
Your program should try to retrieve sizeof of its argument to know how many bytes to swap - perhaps as a third argument - you have no way of telling otherwise how big an argument is. With current function you will overwrite memory which will end up badly - especially in a bigger program. For example, consider a following program.
#include <stdio.h>
int main() {
int a[] = {1, 2, 3, 4, 5, 6, 7, 8};
swap(&a[0], &a[4]);
for (int i = 0; i < 8; i++) {
printf("%d\n", a[i]);
}
}
Which will return 5, 6, 7, 8, 1, 2, 3, 4 - which clearly isn't expected - only 0th and 4th array elements should have been swapped.
It's possible to hide getting size behind a macro if needed.
#define SWAP(a, b) swap(&(a), &(b), sizeof(a))

Haskell Foldr C implementation

I'm trying to implement a version of Haskell's foldr function in C but have hit a wall making it generic as I want to make the + or * characters (char y in foldr) work as addition or multiplication. I was thinking of trying a macro but wasn't sure what would work.
Here the code:
int
foldr(int *v, int (*f)(int*), int x, char y)
{
int temp;
if(*v == (int) NULL) //v is null terminated int array
return x;
else{
temp = *v;
return temp y ((*f)(++v));
}
}
Main issue is making char y work so I can say:
int
sum(int *v)
{
return foldr(v, (sum), 0, '+');
}
and it would just work.
Thanks
I'll show a recursion-based approach. As an exercise, you could turn it into an iterative solution, if you wish.
(Warning: untested)
Haskell:
foldr :: (Int->Int->Int) -> Int -> [Int] -> Int
foldr f x [] = x -- base case
foldr f x (v:vs) = f v (foldr f x vs) -- recursion
C:
int foldr(int (*f)(int,int),
int x,
int *v, size_t length) {
// base case
if (length == 0) return x;
// recursion
return f(*v, foldr(f, x, v+1, length-1));
}
Test:
int add(int a, int b) {
return a+b;
}
int main() {
int a[] = {1,2,3} ;
int res = foldr(add, 0, a, sizeof a/sizeof *a);
printf("%d\n", res);
return 0;
}
If you pass a proper function pointer (like add) above, there is not need to pass the character operator '+'.
Note that functional programming languages also allow to build closures, as in:
let y = 5
in foldr (\x c -> x*y+c) 0 [1..3]
Note how the function \x c -> x*y+c also depends on the value of y. C does not allow to do craft closures, but you can emulate the captured y, if you allow an addition void * argument to the C function.
int foldr(int (*f)(void *, int, int),
void *data,
int x,
int *v, size_t length) {
// base case
if (length == 0) return x;
// recursion
return f(data, *v, foldr(f, data, x, v+1, length-1));
}
Test:
int g(void *data, int x, int c) {
int y = *(int *)data;
return x*y+c;
}
int main() {
int a[] = {1,2,3} ;
int y = 5;
int res = foldr(g, &y, 0, a, sizeof a/sizeof *a);
printf("%d\n", res);
return 0;
}
In this way you can reuse g with different values of y. If you need to capture more variables, pass a pointer to a suitable struct containing all such variables.

Resources