two functions (read and display an array) using pointers to structures - c

I just start to learn pointers to structures and I'm confused.I have to create a type of data ARRAY (which is associated with an array which contains integers.) like a structure which contains: numbers of array's elements and the array's elements stored in a part of memory(heap), dynamically allocated.
So I wrote:
typedef struct ARRAY
{
int nrElem; // number of elements
int *v[100];
};
Now I need to create 2 functions, one for reading an array from keyboard and the second one to display it using the structure I declared.
I tried but I get stuck.
void arrayDisplay(ARRAY *ps)
{
int i;
for(i=0;i<pd->nrElem;++i)
{
printf("%d",)
}
}
void readArray(ARRAY *ps)
{
int i;
for(i=0;i<pd->nrElem;++i)
{
printf("%d",)
scanf("%d",&);
}
}
How to continue?

Instead of an array of pointers int *v[100]; you need an array of ints int v[100]; in your data structure.
See code below:
#include <stdio.h>
#include <stdlib.h>
typedef struct ARRAY
{
int nrElem; // number of elements
int v[100];
} ARRAY;
void arrayDisplay(ARRAY *ps)
{
int i;
for(i=0;i<ps->nrElem;++i)
{
printf("%d\n", ps->v[i]);
}
}
void readArray(ARRAY *ps)
{
int i;
for(i=0;i<ps->nrElem;++i)
{
printf("%d: ", i);
scanf("%d",&ps->v[i]);
}
}
int main()
{
ARRAY a;
a.nrElem = 5;
readArray(&a);
arrayDisplay(&a);
return 0;
}
If you really want to use an array of int pointers you need to allocate the array first. And a different level of redirection for printf and scanf. But I'm not sure why you want to allocate memory for an integer array like this.
typedef struct ARRAY
{
int nrElem; // number of elements
int *v[100];
} ARRAY;
void arrayDisplay(ARRAY *ps)
{
int i;
for(i=0;i<ps->nrElem;++i)
{
printf("%d\n", *ps->v[i]);
}
}
void readArray(ARRAY *ps)
{
int i;
for(i=0;i<ps->nrElem;++i)
{
printf("%d: ", i);
scanf("%d",ps->v[i]);
}
}
int main()
{
ARRAY a;
int i;
a.nrElem = 5;
for(i=0;i<a.nrElem;++i) {
a.v[i] = (int*)malloc(sizeof(a.v[i]));
}
readArray(&a);
arrayDisplay(&a);
return 0;
}

Related

How to allocate a dynamic array of struct

i have a problem with the allocation of a dynamic struct array.
The struct is composed of a char* field, that is another dynamic array of char. After i allocate all arrays, windows block the program when i try to modifty a struct content. Code:
typedef struct
{
char *cod;
}code;
void create_cod(code *singleCode,int codeLength);
void create_codes(code *codes, int codesNumber, int codeLength);
int main()
{
int codesNumber=4, codeLength=10;
code *codes;
create_codes(codes, codesNumber, codeLength);
codes->cod = "abcd"; /*Windows block the program here*/
}
void create_cod(code *singleCode,int codeLength)
{
singleCode->cod = (char*)malloc(codeLength*sizeof(char));
return;
}
void create_codes(code *codes, int codesNumber, int codeLength)
{
codes= (code*)malloc(codesNumber*sizeof(code));
int i=0;
while(i<codesNumber)
{
create_cod(codes+i,codeLength);
i++;
}
return;
}

Trouble assigning value of array element via pointers

I'm having trouble with a certain "program flow" that I'm trying to implement.
The output in the following MWE is supposed to say "Sum: 10" but it says "Sum: 0" because the function set_array_element does not set array elements. Why doesn't it?
#include <stdio.h>
#include <stdlib.h>
typedef struct example example;
struct example {
int nrOf;
double a[];
};
void initialize_example_array(example *e);
void set_array_element(double *el);
example new_example(int nrOf)
{
example *e = malloc(sizeof(example) + nrOf*sizeof(double));
e->nrOf = nrOf;
initialize_example_array(e);
return *e;
}
void initialize_example_array(example *e)
{
printf("%d\n", e->nrOf);
for(int i=0; i<e->nrOf; i++)
{
set_array_element(&e->a[i]);
}
}
void set_array_element(double *el)
{
*el = 1;
}
int main(int argc, const char * argv[]) {
example e = new_example(10);
printf("%d\n", e.nrOf);
int i, s=0;
for(i=0; i<e.nrOf; i++)
{
printf("%f\n", e.a[i]);
s+= e.a[i];
}
printf("Sum: %d\n", s);
return 0;
}
The flexible array member, this is the member a of struct example, is not a pointer. It's address is calculated using the address of the struct.
A struct with a flexible array member cannot be assigned using the simple assignment operator, like it is done in your example:
example e = new_example(10);
where the function returns:
return *e;
You will have to return the pointer:
example* new_example(int nrOf)
{
example *e = malloc(sizeof(example) + nrOf*sizeof(double));
e->nrOf = nrOf;
initialize_example_array(e);
return e;
}
example* e = new_example(10);
printf("%d\n", e->nrOf);
...

How to parse a structure array as a parameter?

How should I parse an array of structures as parameter to a function?
For example, I have the following structure definition:
struct Town
{
char *TownName;
char **GiftList;
int *GiftCount;
int GiftTypes;
};
and a declaration of an array of such structures, in my main:
struct Town TownList[100];
struct Town AuxiliaryStructure;
I have written a custom sorting function for this array, in which I want to make use of each structure's fields, but I do not know how to provide the array TownList[100] to the sort function.
To pass an array of anything to a function, you can just pass a pointer to the first element plus an array length:
struct mystruct {
char* something;
/* ... */
}
struct mystruct myarray[100];
void do_something(struct mystruct* array, int length)
{
int i;
for (i=0; i<length; ++i)
{
array[i].something = ...
}
}
int main(void)
{
do_something(myarray, 100);
return 0;
}
Based on what you wrote, you would reference it in the caller and pass the result. For example:
void sort(char* str){
...
}
int main(){
for(int i=0; i<100; ++i){
sort(array[i].something);
}
}
Alternately you may want to pass the full array and handle it in another function, which would be like this:
void sort(struct mystruct * array){
...
}
int main(){
for(int i=0; i<100; ++i){
sort(array);
}
}
If, on the other hand, you meant that you want to sort the outer array of structures by the contents of something, then you would either have to pass the array as above and implement your own sort, or use a sorting function that takes a function pointer so you can write a comparator. The latter is available in the standard C library, and could be used something like this.
#include <stdlib.h>
int compare_mystruct_by_something(const void *a, const void *b){
return strcmp(((struct mystruct*)a)->something, ((struct mystruct *)b)->something);
}
int main(){
qsort(array, 100, sizeof(struct mystruct), compare_mystruct_by_something);
}

How to "return" an array from a function to main in c

I want to pass an arrays index from my function to main. How can I do that?
For example:
void randomfunction()
{
int i;
char k[20][10];
for (i=0;i<20;i++)
strcpy(k[i], "BA");
}
int main(int argc, char *argv[])
{
int i; for (i=0;i<20;i++) printf("%s",k[i]);
return 0;
}
I know that for you this is very simple but I've found similar topics and they were too complicated for me. I just want to pass the k array to main. Of course my purpose is not to fill it with "BA" strings...
You want to allocate the memory dynamically. Like this:
char** randomfunction() {
char **k=malloc(sizeof(char*)*20);
int i;
for (i=0;i<20;i++)
k[i]=malloc(sizeof(char)*10);
//populate the array
return k;
}
int main() {
char** arr;
int i;
arr=randomfunction();
//do you job
//now de-allocate the array
for (i=0;i<20;i++)
free(arr[i]);
free(arr);
return 0;
}
See about malloc and free.
Here is another option. This works because structs can be copied around , unlike arrays.
typedef struct
{
char arr[20][10];
} MyArray;
MyArray random_function(void)
{
MyArray k;
for (i=0;i<sizeof k.arr / sizeof k.arr[0];i++)
strcpy(k.arr[i], "BA");
return k;
}
int main()
{
MyArray k = random_function();
}
Simplest way:
void randomfunction(char k[][10])
{
// do stuff
}
int main()
{
char arr[20][10];
randomfunction(arr);
}
If randomfunction needs to know the dimension 20, you can pass it as another argument. (It doesn't work to put it in the [] , for historial reasons).

Why can't function access generic parameter

I am slowly learning how to program generic functions in C and get into trouble now and so often. I am making a program that makes a union of two arrays, in this implementation two int arrays. The first problem, which also leads to the second one, is that the compareints (function) does not access one of the passed arguments (void *): I can't figure out why? I been staring at the screen for to long time now...
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//makes union of two generic arrays and eliminates duplicates if there are some...
void **
unite(int (*comp)(void *f, void *s), void **first, void **second, int f_size, int s_size, int bytes, int *x)
{
int i;
void **arr=malloc(bytes*(f_size+s_size));
for(i=0; i<f_size+s_size; i++)
{
/* first bigger */
if(((*comp)(*first, *second))>0)
{
*(arr+i)=*(first++);
}
/* second bigger */
else if(((*comp)(*first, *second))<0)
{
*(arr+i)=*((second++));
}
/* equal => just one copy */
else
{
*(arr+i)=*(first++);
second++;
}
}
*x=i;
return arr;
}
int
compareints(void *first, void *second)
{
if(*((int *)first)>*((int *)second)) //can't access the memoryloc in second...
return 1;
else if(*((int *)first)<*((int *)second))
return -1;
else
return 0;
}
int main(int argc, const char * argv[])
{
int arr[10]={1, 2, 4, 12, 22, 29, 33, 77, 98};
int arr2[5]={3, 5, 7, 8, 9};
void **first=malloc(sizeof(int *)*10);
void **second=malloc(sizeof(int *)*5);
//make pointers to static arrays in dynamic arrays
int f_ind, s_ind;
for(f_ind=0; f_ind<10; f_ind++)
first[f_ind]=&arr[f_ind];
for(s_ind=0; s_ind<5; s_ind++)
second[s_ind]=&arr2[s_ind];
int i;
//make union of the two arrays and print out the result
void **ret=unite(&compareints, first, second, 10, 5, sizeof(int), &i);
for(int k=0; k<i; k++)
printf("%d ", *((int *)ret[k]));
return 0;
}
Why can't function access generic parameter ?
Simple answer to this question is function can access but further manipulation on void * is not possible.
Elements are accessed using pointer arithmetic (which needs size of individual element) since the pointer which is void * pointing to the address you passed but doesn't know about the size of each field in that array or memory location. so accessing or dereferencing will lead you to Undefined Behaviour.
If you want to access each element of that type inside the function then , pass the size of individual element to that function and on that basis make pointer to that same type , then access using new pointer of that type.
For more read this
I tried an approach thanks to #WhozCraigs post about the index going out of bounds. So I made some small mods and now the program does what it intends to.
void **
unite(int (*comp)(void *f, void *s), void **first, void **second, int f_size, int s_size, int bytes, int *x)
{
int i;
int f_ind=0, s_ind=0;
void **arr=malloc(bytes*(f_size+s_size));
for(i=0; i<f_size+s_size; i++)
{
/* first bigger */
if(((*comp)(*first, *second))>0)
{
s_ind++;
if(s_ind<s_size)
*(arr+i)=*(second++);
else
{
f_ind++;
if(f_ind<f_size)
*(arr+i)=*(first++);
else
break;
}
}
/* second bigger */
else if(((*comp)(*first, *second))<0)
{
f_ind++;
if(f_ind<f_size)
*(arr+i)=*(first++);
else
{
s_ind++;
if(s_ind<s_size)
*(arr+i)=*(second++);
else
break;
}
}
/* equal => just one copy */
else
{
f_ind++;
s_ind++;
if(f_ind<f_size && s_ind==s_size)
{
*(arr+i)=*(first++);
}
else if(f_ind==f_size && s_ind<s_size)
{
*(arr+i)=*(second++);
}
else
{
*(arr+i)=*(first++);
second++;
}
}
}
*x=i;
return arr;
}

Resources