How to refactor a function with different struct pointers as parameters? - c

Suppose I have this piece of code, with 2 structs and a big function that receives this 2 structs as parameters:
typedef struct
{
int field_A;
int field2_A;
} A;
typedef struct
{
int field_B;
int field2_B;
} B;
void function_need_refactor(A *a, B *b)
{
for(i = 0; i < SIZE; i++)
{
do_something(a->field_A);
}
for(i = 0; i < SIZE; i++)
{
do_something(b->field2_B);
}
}
How can I replace the both for loops to a single function? I thought about using void pointer and an identifier for each struct, but couldn't come up with an answer. Is there a clean way to refactor this or is it impossible?
void refactored_function(void* my_struct, char type_identifier)
{
//code to identify the type
for(i=0; i < SIZE; i++)
{
do_something((cast)my_struct->????);
}
}

There are two modifications that come to mind here. First of all, both loops rely on the same counter and the counter is independent of the items in the loop body... Thus, logically, you should at least be able to do this:
typedef struct
{
int field_A;
int field2_A;
} A;
typedef struct
{
int field_B;
int field2_B;
} B;
void function_need_refactor(A *a, B *b)
{
for(i = 0; i < SIZE; i++)
{
do_something(a->field_A);
do_something(b->field2_B);
}
}
But you may also be able to refactor do_something() to operate on both:
typedef struct
{
int field_A;
int field2_A;
} A;
typedef struct
{
int field_B;
int field2_B;
} B;
void function_need_refactor(A *a, B *b)
{
for(i = 0; i < SIZE; i++)
{
do_something(a->field_A, b->field2_B);
}
}
That way, you're only using one loop total, and the function is handling both fields on each loop iteration.

Related

Function to generate random ints in array doesn't work

My function does not work and I do not know why, it ends after entering the range. Could you explain why and how to fix it? I need to do this using these pointers to the array.
void generate(int *pa, int *pa2);
void display(int *pa, int *pa2);
int main()
{
srand(time(0));
int size;
printf("Enter size of array\n");
scanf("%d",&size);
int *A=(int*) malloc(size*sizeof(int));
int *ptr=A;
int *pa=&ptr[0];
int *pa2=&ptr[size-1];
generate(pa,pa2);
display(pa,pa2);
return 0;
}
void generate(int *pa, int *pa2)
{
int upper,lower;
int randi;
printf("enter range");
scanf("%d %d",&lower,&upper);
for (int i = 0; i <*pa2; i++)
{
randi=(rand() % (upper - lower + 1)) + lower;
*(pa+i) = randi;
}
}
for (int i = 0; i <*pa2; i++)
You've mixed up iterating by index with iterating until you hit a pointer. That's comparing the value of the end of the array, which is garbage, to i.
Instead you need to compare the pointers pa+1 to pa2. And it has to be <= because you do want to fill in the last item.
for (int i = 0; (pa+i) <= pa2; i++) {
*(pa+i) = ...
}
But it's easier to get rid of i and increment a pointer directly.
void generate(int *start, int *end) {
...
for(int *current = start; current <= end; current++) {
*current = ...;
}
}
But since you have the size, it's simpler to pass in the size and iterate by index.
void generate(int *array, int size) {
...
for (int i = 0; i <= size; i++) {
array[i] = ...
}
}
And you can simplify calling the function. A and &A[0] point to the same memory.
generate(A, &A[size-1]);

Issue with linked list and truth table

So I'm trying to print the truth table of a gate with n inputs using linked lists. I tried the following but I'm running into a problem. If I use the for loops with bincombs, to print all possible combinations and to calculate the result, on both report and myandlst as shown below, it crashes. The problem is easily fixed if I print everything in myandlst but I want to avoid it. Here is my code so far:
#include <stdio.h>
#include <stdlib.h>
typedef struct data
{
int value;
struct data * next;
} Data;
typedef Data * DataList;
typedef int (*CallBack)(DataList *inlist, int n);
int report(CallBack f, int n);
int getbit(int x, int p);
void bincombs(int * x, int n);
int myandlst(DataList *list, int n);
int main( )
{
CallBack f ;
report(myandlst, 4);
return 0;
}
int getbit(int x, int p)
{
return (x & (1<<p))!=0;
}
void bincombs(int * x, int n)
{
static int state = 0 ;
int i;
for (i=0; i<n; i++)
{
*x = getbit (state, i);
x++;
}
state ++;
return;
}
Data * createData( int value)
{
Data * dataptr;
dataptr = malloc(sizeof (Data));
dataptr->value = value;
dataptr->next = NULL;
return dataptr;
}
void appendData(DataList *lstptr, Data *newptr)
{
if (*lstptr==NULL)
{
*lstptr = newptr;
return;
}
appendData( &((*lstptr)->next), newptr);
return;
}
int myandlst (DataList *inlist, int n)
{
int i,j,k;
int * x = malloc (n*sizeof(int));
k=1;
for (i=0; i< (1<<n) ; i++)
{
bincombs(x, n);
for (j=n-1; j>=0; j--)
{
k*=x[j];
}
appendData(inlist,createData(k));
k=1;
}
return 0;
}
int report(CallBack f, int n)
{
DataList temp ;
int * x = malloc (n*sizeof(int));
int i,j;
f(&temp, n);
for (i=0; i< (1<<n) ; i++)
{
bincombs(x, n);
for (j=n-1; j>=0; j--)
printf("%d ", x[j]);
printf("%d\n", temp -> value);
temp = temp->next;
}
printf("\n");
return 0;
}
P.S This is an assignment and therefore the structure of the program is standard. I can't avoid using linked lists or changing the format of the functions too much.

How to pass a structure array element as argument to function?

#include<stdio.h>
struct Ques
{
int a;
}Q[5];
void sort(int a[])
{
printf("any sort technique...");
}
void main()
{
sort(Q.a);
}
So this is the sample code.
I Want to access the whole struct element as array.
You want this:
#include<stdio.h>
struct Ques
{
int a;
} Q[5];
void sort(struct Ques array[], int size)
{
printf("any sort technique...");
// just some demo
for (int i = 0; i < size; i++)
printf("array[%d].a = %d\n", i, array[i].a);
}
int main()
{
// put some data into Q
sort(Q, 5);
}
sort needs two parameters:
the pointer to the array to sort
the size of the array (unless you only ever want to sort array of some fixed size

Function to slice an array or struct in c

I have written a function to slice an array in c but it returns addresses I think. I did work correctly once but I screwed up somewhere, any help would be appreciated.
#include <stdio.h>
#include <stdlib.h>
int slice_array(int *input_array, int *sliced_array, int n){
int i;
for(i=0; i < n; i++) {
sliced_array[i] = input_array[i];
return 0;
}
};
struct nbrs_ind {
float value;
int index;
};
//I also want to write a function which can slice the members of struct nbrs_ind (i.e. just slice first n indices nbrs_ind)
int main () {
int k=4;
int i;
int a[7] = {1,2,3,4,6,5,7};
int *ptr_a = a;
int b[k];
int *ptr_b = b;
slice_array(a,b,k);
for(i=0;i<k;i++) {
printf("%d\t",b[i]);
}
printf("\n");
}
~
Update, slicing the array works fine but I want to so the same with struct so far I have written the following code. I get he following error:
assignment from incompatible pointer type [enabled by default]
ptr_A = &A;
#include <stdio.h>
#include <stdlib.h>
//This function works fine in drivers program
void slice_array(int *input_array, int *sliced_array, int n){
int i;
for(i=0; i < n; i++) {
sliced_array[i] = input_array[i];
}
};
struct nbrs_ind {
float value;
int index;
};
//Need to make the slice of nbrs_ind struct using following function.
void slice_struct(struct nbrs_ind *input_struct, struct nbrs_ind *sliced_struct, int n){
int i;
for(i=0; i < n; i++) {
sliced_struct[i].index = input_struct[i].index;
sliced_struct[i].value = input_struct[i].value;
}
};
int main () {
int k=3;
int i;
int a[7] = {1,2,3,4,6,5,7};
float c[7] = {2.3,10,3,5,6.4,7.3,1};
int *ptr_a = a;
int b[k];
int *ptr_b = b;
struct nbrs_ind A[7]; // Declare 7 struct of nbrs_ind
//Initilize the delare structs
for (i=0;i<7;i++){
A[i].index = i;
A[i].value = c[i];
}
//How do I make a pointer to the struct so I can pass it to slice_struct function
// I need to be able to do something like slice_struct(A,B,n);
struct nbrs_ind *ptr_A ;
ptr_A = &A;
slice_array(a,b,k);
for(i=0;i<k;i++) {
printf("%d\t",b[i]);
}
printf("\n");
}
~
~
~
#include <stdio.h>
#include <stdlib.h>
int slice_array(int *input_array, int *sliced_array, int n){
int i;
for(i=0; i < n; i++) {
sliced_array[i] = input_array[i];
}
return 0;
};
struct nbrs_ind {
float value;
int index;
};
//I also want to write a function which can slice the members of struct nbrs_ind (i.e. just slice first n indices nbrs_ind)
int main () {
int k=4;
int i;
int a[7] = {1,2,3,4,6,5,7};
int *ptr_a = a;
int b[k];
int *ptr_b = b;
slice_array(a,b,k);
for(i=0;i<k;i++) {
printf("%d\t",b[i]);
}
printf("\n");
}

How to pass an array of structures to a function by reference in C?

This code is similar to what I am attempting to do, however I am getting errors saying that I am passing incompatable types
#include <stdio.h>
struct numbers{
int num;
};
void fillArray(struct numbers* a[]);
int main(void)
{
struct numbers array[4];
fillArray(&array);
for(int i = 0; i < 4; i++)
{
printf("%d", array[i].num);
}
}
void fillArray(struct numbers* a[])
{
for(int i = 0; i < 4; i++)
{
a[i]->num = i;
}
}
The function parameter
void fillArray(struct numbers* a[]);
is adjusted to
void fillArray(struct numbers ** a);
On the other hand the type of the argument in this call
fillArray(&array);
is struct numbers( * )[4]. The types struct numbers ** and struct numbers ( * )[4] are incompatible.
There is no need to pass a pointer to the array because elements of the array are already passed indirectly if you will pass just the array that is implicitly converted to pointer to its first element.
So what you need is to declare and define the function like
void fillArray( struct numbers a[] )
// or
// void fillArray( struct numbers *a )
{
for(int i = 0; i < 4; i++)
{
a[i].num = i;
}
}
and call it like
fillArray( array );
Take into account that the function depends on magic number 4. It is better to define the function such a way that it could deal with arrays of various numbers of elements.
So I would define the function like
void fillArray( struct numbers a[], size_t n )
// or
// void fillArray( struct numbers *a, size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
a[i].num = i;
}
}
and call it like
fillArray( array, 4 );
Here is demonstrated how the program can look in whole
#include <stdio.h>
struct numbers
{
int num;
};
void fillArray( struct numbers a[], size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
a[i].num = i;
}
}
#define N 4
int main(void)
{
struct numbers array[N];
fillArray( array, N );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", array[i].num );
}
putchar( '\n' );
return 0;
}
Its output is
0 1 2 3
To use an array with a different number of elements it is enough to change the value of the macro name N. Thus the program and its function do not depend on the magic number 4.
You probably want this:
#include <stdio.h>
struct numbers {
int num;
};
void fillArray(struct numbers a[]);
int main(void)
{
struct numbers array[4];
fillArray(array);
for (int i = 0; i < 4; i++)
{
printf("%d\n", array[i].num);
}
}
void fillArray(struct numbers a[])
{
for (int i = 0; i < 4; i++)
{
a[i].num = i;
}
}
Your function wants an array of pointers, but you have a single array, so
void fillArray(struct numbers* a);
or
void fillArray(struct numbers a[]);
Moreover using a[i] you are already dereferencing the pointer, so you need . not -> operator.
#include <stdio.h>
struct numbers
{
int num;
};
void fillArray(struct numbers *a);
int main(void)
{
struct numbers array[4];
fillArray(array);
for (int i = 0; i < 4; i++)
{
printf("%d", array[i].num);
}
printf("\n");
}
void fillArray(struct numbers *a)
{
for (int i = 0; i < 4; i++)
{
a[i].num = i;
}
}
Finally using c array decays to pointer to first item of array, so
fillArray(&array);
must be
fillArray(array);
or
fillArray(&array[0]);
Lastly you should pass size of array to your function, instead of using fixed numbers. You can do it using pointer and size
#include <stdio.h>
struct numbers
{
int num;
};
void fillArray(size_t size, struct numbers *a);
int main(void)
{
struct numbers array[4];
fillArray(sizeof(array)/sizeof(array[0]), array);
for (int i = 0; i < 4; i++)
{
printf("%d", array[i].num);
}
printf("\n");
}
void fillArray(size_t size, struct numbers *a)
{
for (size_t i = 0; i < size; i++)
{
a[i].num = i;
}
}
Or using VLAs
#include <stdio.h>
struct numbers
{
int num;
};
void fillArray(size_t size, struct numbers a[size]);
int main(void)
{
struct numbers array[4];
fillArray(sizeof(array)/sizeof(array[0]), array);
for (int i = 0; i < 4; i++)
{
printf("%d", array[i].num);
}
printf("\n");
}
void fillArray(size_t size, struct numbers a[size])
{
for (size_t i = 0; i < size; i++)
{
a[i].num = i;
}
}
It is sufficient to only mention the array name. The compiler will transform it into a pointer to the first element.
So instead of
fillArray(&array);
you write
fillArray(array);
Though this answers your question, of course the function being called must have a compatible definition, which in your case is not so.

Resources