struct and typedef initialization - c

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

Related

Foreach function in C

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);
}

Pass in part of an array as function argument

I have an array int arr[5] = {10, 2, 3, 5, 1}, and I want to pass in the last 4 elements (basically from index 1 to index4) into an argument as an array (so: [2, 3, 5, 1]). Is there a way to do this very simply (like how in Ruby you would be able to do arr[1..4]), or would I have to use a for loop?
You can manually increment the pointer by 1:
your_function(arr + 1)
Pointer arithmetic in C implicitly accounts for the size of the elements, so adding 1 will actually add 1 * sizeof(int)
For a closer analogue to array slicing from other languages, try this function:
int *slice_array(int *array, int start, int end) {
int numElements = (end - start + 1)
int numBytes = sizeof(int) * numElements;
int *slice = malloc(numBytes);
memcpy(slice, array + start, numBytes)
return slice;
}
It makes a slice of the array between the given start and end indices. Remember to free() the slice once you're done with it!
Answer
Given you current code:
int arr[5] = {10, 2, 3, 5, 1};
You can duplicate the range 1..4 by:
int arr_dup[4];
memcpy(arr_dup,arr+1,sizeof(int)*4);
Remember that your function definition should be a pointer, example:
void a_function(int *arr_arg); //Call via a_function(arr_dup);
Explanation
Arrays in c implemented as pointers (aka variables that hold memory addresses).
If you do arithmetic on the pointer, it will advance to the respective element. Example:
ptr + 1 //Next Element
ptr - 1 //Previous Element
#include <stdio.h>
#include <stdlib.h>
void my_function(int arr_size, int *arr)
{
int i;
for(i=0; i < arr_size; i++)
{
printf("[%d]:%d\n", i, arr[i]);
}
}
int main(int argc, char **argv)
{
int arr[] = { 10, 2, 3, 5, 1 };
(void)my_function(4, &arr[1]); /* TODO > use more flexible indexing */
return EXIT_SUCCESS;
}
I think you can use memcpy,memcpy can copy data byte to byte.In memmory,our data is binary,so even int is 4 bytes,we can copy it byte to byte.
int dst[4];
memcpy(dst,&arr[1],size(int) * 4);

C program to compute length of array

I'm learning C, and tried writing a function that, given an array of integer, returns the length of the array. Here is my code:
#include <stdio.h>
int length_of_array(int array[])
{
int length = 0;
int i = 0;
while (array[i] != '\0') {
length += 1;
i += 1;
}
return length;
}
int main()
{
int test_array[] = {1, 2, 3, 4, 5};
printf("%d\n", length_of_array(test_array));
return 0;
}
However, when I compile this code and run it, I says that the length of the array passed in is 14. Does anyone know what could be the problem here?
Strings in C are NUL-terminated. Arrays are not (unless you explicitly do it yourself). The size of array is just the size of array: if allocated as a constant, you can find out the size with sizeof operator. If all you have is a plain pointer, you need to remember the size - there is no way in C to get it once you forget it.
#include <stdio.h>
int main() {
int test_array[] = {1, 2, 3, 4, 5};
int *test_ptr = test_array;
printf("%lu\n", sizeof(test_array) / sizeof(*test_array)); // correct
printf("%lu\n", sizeof(test_ptr) / sizeof(*test_ptr)); // incorrect
return 0;
}

Length of 2D array[i]

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);
}
}

why does GCC "expect an expression"?

#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.

Resources