I want to create a function that takes a array and a function and calls that function on each element in the array
I've looked around for a solution but they all seem to use macros whereas I would prefer a function if at all possible.
I'm looking for something that would work something like the following
void print_string()
{
printf("%d\n", num);
}
int array[] = { 1, 2, 3, 4, NULL }; // So the foreach function knows when it has reached the end
for_each_function(array, print_number);
Outputting:
1
2
3
4
Edit: It needs to be generic so it will probably require a macro
You should probably use function pointers. One complete implementation using function pointers is like this.
#include <stdio.h>
void for_each(int * arr, int size, void (*fun)(int))
{
for (int i = 0; i < size; i++)
{
(*fun)(arr[i]);
}
}
void print_num(int num)
{
printf("%d\n", num);
}
int main()
{
int array [] = {1, 2, 3, 4};
for_each(array, 4, print_num);
return 0;
}
Use a function pointer, like this:
#include <stdio.h>
void for_each_function(int* arr, size_t size, void(*fun)(int)) {
for(size_t i = 0; i < size; ++i)
(*fun)(arr[i]);
}
void print_number(int);
int main(void) {
int array[] = { 1, 2, 3, 4 };
for_each_function(array, 4, &print_number);
return 0;
}
void print_number(int num)
{
printf("%d\n", num);
}
Output:
1
2
3
4
Remarks:
The third parameter of for_each_function, namely void(*fun)(int),
is a function pointer named fun, with a return type void, and a
parameter of type int.
Inside the for each body, you call the function pointer like this
(*fun)(arr[i]);, which dereferences the function pointer fun, and
would pass arr[i] as its parameter. You could also use fun(arr[i]).
In the call of the for each function in main function, you need to
use the address of the function you want to point to, like this
for_each_function(array, 4, &print_number);. You could also use for_each_function(array, 4, print_number);.
PS: In your example array, I don't think you wanted to use NULL as the last element (you would probably get a warning like warning: initialization of 'int' from 'void *' makes integer from pointer without a cast [-Wint-conversion], unless NULL was defined as 0, as commented by #EricPostpischil), so I got rid of it in my example.
A modification of the answer of davidlowryduda / gsamaras to be compatible with any type of array, not just int, however that impacts the called function which gets a pointer rather than a value :
#include <stdio.h>
void for_each(void * arr, size_t nElts, size_t sizeElt, void (*fun)(void *))
{
char * p = arr;
for (size_t i = 0; i < nElts; i++)
{
(*fun)(p);
p += sizeElt;
}
}
/* for_each can be called directly or via the following macro,
the array can be an expression without any problem : is it given
in argument and the other uses are only for sizeof */
#define FOR_EACH(a, f) for_each(a, sizeof(a)/sizeof(*a), sizeof(*a), f)
void print_int(void * p)
{
printf("%d\n", *((int *) p));
}
void print_short(void * p)
{
printf("%d\n", *((short *) p));
}
int main()
{
int iarray [] = {1, 2, 3, 4};
FOR_EACH(iarray, print_int); /* for_each(iarray, sizeof(iarray)/sizeof(*iarray), sizeof(*iarray), print_int); */
short sarray [] = {5, 6, 7, 8};
FOR_EACH(sarray, print_short); /* for_each(sarray, sizeof(sarray)/sizeof(*sarray), sizeof(*sarray), print_short); */
return 0;
}
Compilation and execution:
pi#raspberrypi:~ $ gcc -pedantic -Wall -Wextra i.c
pi#raspberrypi:~ $ ./a.out
1
2
3
4
5
6
7
8
You can define a macro for this.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FOR_EACH(type, target, size, body) \
\
for (size_t i = 0; i < size; i++) \
{ \
type value = target[i]; \
body; \
}
int main(int argc, char const *argv[])
{
int arr[4] = {0, 1, 2, 3};
char *name = "My Name";
FOR_EACH(int, arr, 4, {
printf("%d\n", value);
})
size_t len = strlen(name);
FOR_EACH(char, name, len, {
printf("%c-", value);
})
return 0;
}
In this case you don't even need a function and it can be used to iterate over any array of any type as long as you know its length.
You could do something like that using function pointers. But using macros would be very more powerful, it will allow your foreach to be generic.
#include <stdio.h>
typedef struct int_array{
int *data;
int len;
}Int_array;
void print_number(int num)
{
printf("%d\n", num);
}
void for_each_function(Int_array a, void (*f)(int)){
for(int i =0; i < a.len;i++){
(*f)(a.data[i]);
}
}
int main(){
int data[4] = { 1, 2, 3, 4 };
Int_array x;
x.len = 4;
x.data = data;
for_each_function(x, print_number);
}
I took a solution's friend on forum and I increased.
I got the idea that foreach doesn't have to have a value to stop the loop.
#include <iostream>
#include <stdio.h>
void for_each(int * arr, void (*fun)(int)){
for (int i = 0; i < arr[i]; i++){
(*fun)(arr[i]);
}
}
void print_num(int num){
printf("%d\n", num);
}
int main(){
int array [] = {1, 2, 3, 4, 5, 6};
for_each(array, print_num);
}
Related
I am not sure why I am not getting a display on the console for the value of maxProd. I think I am declaring the arr_integer array variable wrong in main?
I ran a couple tests and the program looks like it does not even get to call solution().
Any help would be greatly appreciated. I am trying to get this to work and get rid of the following warnings;
Adjacent_Element_Product.c:31:40: note: (near initialization for 'array')
Adjacent_Element_Product.c:31:43: warning: excess elements in struct initializer
#include <stdio.h>
typedef struct arr_integer {
int size;
int *arr;
} arr_integer;
arr_integer alloc_arr_integer(int len) {
arr_integer a = {len, len > 0 ? malloc(sizeof(int) * len) : NULL};
return a;
}
int solution(arr_integer inputArray) {
int maxProd = inputArray.arr[0] * inputArray.arr[1];
for (int i = 1; i < inputArray.size - 1; i++)
{
int product = inputArray.arr[i] * inputArray.arr[i + 1]; //multiple next door neighbours.
if (product > maxProd)
maxProd = product;
}
return printf("maxProd: %d\n", maxProd);
}
int main()
{
arr_integer array = {3, 6, -2, -5, 7, 3};
solution(array);
return 0;
}
The problem is that you don't allocate memory for the array and that it then tries to use the list of integers as an int*.
A possible remedy:
#define Size(x) (sizeof (x) / sizeof *(x))
int main() {
int ints[] = {3, 6, -2, -5, 7, 3};
arr_integer array = {.size = Size(ints), .arr = ints};
solution(array);
}
Here are the relevant changes:
added <stdlib.h> for malloc
eliminated alloc_arr_integer() which was not used
maxProd is initialized to INT_MIN and tweaked initial loop condition to reduce duplication
to make the solution a little smaller passing the value inline to solution (#TedLyngmo probably gave you a better solution)
Not fixed:
arr_integer doesn't seem to add any value so maybe just pass size and array to solution(). You could create a macro to initialize it using the approach #TedLyngmo shared with you. It has to be a macro as int [] degrades to int * in a function call, and the latter (silently?) gives you the wrong result which makes it error prune.
Does negative size make sense? If not then use an unsigned type.
What is the solution if size < 2?
solution() returns the value from printf() which is strange. You might want to return maxProd and have main() print out the value. This makes your function testable
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct arr_integer {
int size;
int *arr;
} arr_integer;
int solution(arr_integer inputArray) {
int maxProd = INT_MIN; // what is answer if size < 2? error?
for (int i = 0; i < inputArray.size - 1; i++) {
int product = inputArray.arr[i] * inputArray.arr[i + 1]; //multiple next door neighbours.
if (product > maxProd)
maxProd = product;
}
return printf("maxProd: %d\n", maxProd);
}
int main() {
solution((arr_integer) {
6,
(int []) { 3, 6, -2, -5, 7, 3 }
});
return 0;
}
and the output is:
maxProd: 21
I have coded a generic insertion sort in C, and it works really fine.
But, On my function of insertion sort, it gets a void** arr,
and on its signature it gets a void* arr, otherwise, it doesn't work.
Why is it so?
Do we have any other ways to code the insertion sort to be generic?
The Full code is here:
#include <stdio.h>
#include <malloc.h>
#define SIZE 10
int cmp(void* elm1, void* elm2);
void insertionSort(void* arr, int size);
int main()
{
int arr[] = {5, 8, 2, 3, 15, 7, 4, 9, 20, 13};
int arr2[] = {1};
int i;
for (i = 0; i < SIZE; i++)
printf("%d ", arr[i]);
printf("\n");
insertionSort(&arr, SIZE);
for (i = 0; i < SIZE; i++)
printf("%d ", arr[i]);
return 0;
}
void insertionSort(void** arr, int size)
{
int i = 1;
int j;
void* temp;
while (i < size)
{
if (cmp(arr[i], arr[i-1]) == -1)
{
temp = arr[i];
j = i - 1;
while (j >= 0 && cmp(arr[j], temp) == 1)
{
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
}
i++;
}
}
int cmp(void* elm1, void* elm2)
{
if ((int)elm1 == (int)elm2)
return 0;
else if ((int)elm1 > (int)elm2)
return 1;
else
return -1;
}
The code as it is, is undefined, because of multiple problems. It just happens to work, because on your system the size of the pointer is the same as the size of the type int.
You code will not compile without warnings (if you enable them). The function insertionSort and it's prototype must have the same type.
You should change the type in the function definition to
void insertionSort(void* arr, int size)
And then cast the pointer arr, to an appropriate type. Since this is a generic sort, like qsort(), the only realistic option is a cast to char*. This means you will also have to pass the size of the type into the function, so the pointer can be incremented correctly. This will require you to change the function drastically.
So, the function prototype should really be the same as qsort:
void Sort(void* arr, size_t size , size_t object_size , int(*)( const void* , const void* ))
The problem is that integers are not pointers, so your test array is of type *int or int[]. But in your function, you don't know that and you try to make your code work with pointers. So you expect * void[]. If you change your temp variable to int, you don't need the ** in the signature. The same way, if you want to keep the "generic" (as you call), you need an array of *int.
Basically, in C you cannot write a function working out of the box for both primary types and pointers. You need some tricks. Have a look at this stackoverflow, maybe it will help.
I'm working in C, and am attempting to replicate the length member function that other languages (ie: C++) use to determine the length of an array or possibly vector of data. Is this something I can accomplish in C, or do I have to fall back onto examples like this:
int arraySize = sizeof(array) / sizeof(array[0]);
In general, in C, you use arrays as they are: a contiguous set of multiple pieces of data of the same type. You are generally expected to keep track of array sizes, along with the size of individual members, yourself.
In C++, for example, you have access to the Vector class, which encapsulates and handles all this record keeping for you.
In C, you would be expected to know exactly how big the array is. This is especially important in the case of pointer decay. Your initial example...
int arrayOfInts[6] = {1, 2, 3, 4, 5, 6};
int sizeOfArray = sizeof(arrayOfInts) / sizeof(int); // Success; Returns "6"
This works in this case, but it will fail if you were to pass the array to a function expecting an array of integers (as a pointer) as a function argument.
#include <stdio.h>
int getArraySize(int* arr);
int main(void) {
int arrayOfInts[6] = {1, 2, 3, 4, 5, 6};
int sizeOfArray = getArraySize(arrayOfInts);
return 0;
}
int getArraySize(int* arr) {
int ret;
ret = sizeof(arr) / sizeof(int); // FAILS, returns the size of a pointer-to-int, not the size of the array
return ret;
}
There are two ways to handle this: static definitions, or careful dynamic memory management.
// CASE 1: Trivial case, all arrays are of a static fixed size
#include <stdio.h>
#define ARR_SIZE (6)
int getArraySize(int* arr);
int main(void) {
int arrayOfInts[ARR_SIZE] = {1, 2, 3, 4, 5, 6};
int sizeOfArray = getArraySize(arrayOfInts);
return 0;
}
int getArraySize(int* arr) {
return ret ARR_SIZE;
}
// CASE 2: Managing sizes with dynamic allocation
#include <stdio.h>
#define ARR_SIZE (6)
int main(void) {
int sizeOfArray = ARR_SIZE;
int* arrayOfInts = malloc(sizeOfArray*sizeof(int));
if (arrayOfInts != NULL) {
// Success; initialize
int i;
for (i=0; i<sizeOfArray; i++) {
arrayOfInts[i] = i;
}
return 0;
} else {
// Failed; abort
sizeOfArray = 0;
return (-1);
}
}
I want to initialize an array of size 5 pointers that holds pointers to functions that have no parameters and which returns an int (could be any function that facilitate these requirements).
This is what i tried thus far but i get a syntax error:
int (*func)() fparr[5] = int (*func)();
What is wrong with this syntax?
If the function you want to supply as the default contents of the array is called func, then
you better use a typedef,
you have to use an array initializer
Consider:
typedef int (*IntFunc)(void);
IntFunc fparr[5] = { func, func, func, func, func };
Or the less readable way, if you prefer to avoid typedef:
int (*fparr[5])(void) = { func, func, func, func, func };
Because you are not actually initialising an array of function pointers ... try:
int (*fparr[5])(void) = { func1, func2, func3, func4, func5 };
Step 1:
define the signature of the functions as a type FN:
typedef int (*FN)();
Step2:
define the 5 functions with the FN signature:
int f1(void) { ; }
int f2(void) { ; }
...
Step 3:
define and initialize an array of 5 functions of type FN:
FN fparr[5] = {f1,f2,f3,f4,f5}
otherwise:
If you do not want to define a separate signature, you can do it -- as said before -- so:
int ((*)fpar []) () = {f1,f2, ...}
If you know the number of functions from the array at the moment of declarations, you do not need to write 5, the compiler allocated this memory for you, if you initialize the array at the same line as the declaration.
Well, I'm late...
#include <stdio.h>
int fun0()
{
return 0;
}
int fun1()
{
return 1;
}
int fun2()
{
return 2;
}
int main(int argc, char* argv[])
{
int (*f[]) (void) = {fun0, fun1, fun2};
printf("%d\n", f[0]());
printf("%d\n", f[1]());
printf("%d\n", f[2]());
return 0;
}
An array of function pointers can be initialized in another way with a default value.
Example Code
#include <stdio.h>
void add(int index, int a, int b){
printf("%d. %d + %d = %d\n", index, a, b, a + b);
}
void sub(int index, int a, int b){
printf("%d. %d - %d = %d\n", index, a, b, a - b);
}
int main(){
void (*func[10])(int, int, int) = {[0 ... 9] = add};
func[4] = sub;
int i;
for(i = 0; i < 10; i++)func[i](i, i + 10, i + 2);
}
If you run the above program, you will have the below output. All elements are initialized with function add, but 4th element in array is assigned to function sub
Output
0. 10 + 2 = 12
1. 11 + 3 = 14
2. 12 + 4 = 16
3. 13 + 5 = 18
4. 14 - 6 = 8
5. 15 + 7 = 22
6. 16 + 8 = 24
7. 17 + 9 = 26
8. 18 + 10 = 28
9. 19 + 11 = 30
I just add a bit more to the above answers. Array of function pointers can be indexed by an enum variable, showing the type of operation for each index. Take a look at the following example. Here, we use tyepdef for function pointer operator. Then we create an array of this function pointer called act. Finally, we initialize the array to the increment and decrement functions. In this case, index 0 is referred to increment and index 1 is referred to decrement. Instead of using this raw indexing, we use enum which has INCR, and DECR, corresponding to index 0, 1.
#include<stdio.h>
#include<stdlib.h>
typedef void (*operate)(int *, int);
void increment(int *, int);
void decrement(int *, int);
enum {
INCR, DECR
};
int main(void){
int a = 5;
operate act[2] = {increment,decrement};
act[INCR](&a,1);
printf("%d\n",a);
act[DECR](&a,2);
printf("%d\n",a);
return 0;
}
void increment(int *a, int c){
*a += c;
}
void decrement(int *a, int c){
*a -= c;
}
Here is a working example showing the correct syntax:
#include <stdio.h>
int test1(void) {
printf("test1\n");
return 1;
}
int test2(void) {
printf("test2\n");
return 2;
}
int main(int argc, char **argv) {
int (*fparr[2])(void) = { test1, test2 };
fparr[0]();
fparr[1]();
return 0;
}
Example code:
static int foo(void) { return 42; }
int (*bar[5])(void) = { foo, foo, foo, foo, foo };
Note that the types int (*)() and int (*)(void) are distinct types - the former denotes a function with a fixed but unspecified number of arguments, whereas the latter denotes a function with no arguments.
Also note that the C declarator syntax follows the same rules as expressions (in particular operator precedence) and is thus read inside-out:
bar denotes and array (bar[5]) of pointers (*bar[5]) to functions (int (*bar[5])(void)). The parens (*bar[5]) are necessary because postfix function calls bind more tightly than prefix pointer indirection.
#define rows 2
#define cols 2
#define NUM_CORNERS 4
int main(void) {
int i;
int the_corners[NUM_CORNERS];
int array[rows][cols] = {{1, 2}, {3, 4}};
corners(array, the_corners);
for (i = 0; i < 4; i++) printf("%d\n", the_corners[i]);
}
int corners (int array[rows][cols], int the_corners[]) {
the_corners = {
array[0][cols-1],
array[0][0],
array[rows-1][0],
array[rows-1][cols-1]
};
}
I get these weird errors and i have no idea why:
prog.c: In function ‘main’:
prog.c:10: warning: implicit declaration of function ‘corners’
prog.c: In function ‘corners’:
prog.c:15: error: expected expression before
The the_corners = { ... } syntax is an array initialization, not an assignment. I don't have a copy of the standard handy so I can't quote chapter and verse but you want to say this:
void corners (int array[rows][cols], int the_corners[]) {
the_corners[0] = array[0][cols-1];
the_corners[1] = array[0][0];
the_corners[2] = array[rows-1][0];
the_corners[3] = array[rows-1][cols-1];
}
I also took the liberty of changing int corners to void corners as you weren't returning anything. And your main also needs a return value and you forgot to #include <stdio.h>.
You're trying to use an initialiser expression as an assignment. This isn't valid, even in C99, because the type of the_corners is int*, not int[4]. In this case you would be best off assigning each element individually.
The main doesn' know about your function. Either move the function decleration above the main or prototype it before the main:
int corners (int array[rows][cols], int the_corners[NUM_CORNERS]);
Try this one:
#include <stdio.h>
#define NROWS 2
#define NCOLUMNS 2
#define NCORNERS 4
int corners(int (*arr)[NCOLUMNS], int* the_corners);
int main() {
int i;
int the_corners[NCORNERS];
int arr[NCOLUMNS][NROWS] = {{1, 2}, {3, 4}};
corners(arr, the_corners);
for (i = 0; i < NCORNERS; i++)
printf("%d\n", the_corners[i]);
return 0;
}
int corners(int (*arr)[NCOLUMNS], int* the_corners) {
the_corners[0] = arr[0][NCOLUMNS-1];
the_corners[1] = arr[0][0];
the_corners[2] = arr[NROWS-1][0];
the_corners[3] = arr[NROWS-1][NCOLUMNS-1];
return 0;
}
You can read here about passing a 2D array to a function.