control double pointer on array of structs - c

I need to print a name for pointer.
But it doesn't works at all. Console stops..
Maybe the problem will be on 'find_young' function.
I don't know what's the problem and how to fix it.
What can I do for a right code.
Below are my codes.
========
typedef struct {
char *name;
int age;
} PERSON;
PERSON s[3] = { {"ACE", 25}, {"HEART" ,28}, {"CLOVER", 40} };
void find_young(PERSON **p) {
int i;
for (i = 0; i < 1; i++) {
if (s[i].age > s[i+1].age) {
p = &s[i+1];
}
}
};
void Ex1()
{
struct PERSON *p;
p = &s[0];
find_young(&p);
printf("youngest man is %s.", p->name);
}

You are assigning between wrong types, and the compiler should warn you about it:
p = &s[i + 1];
Here the expression &s[i + 1] is a pointer to PERSON, but p is a pointer to a pointer to PERSON. Not quite the same thing.
What you want is
*p = &s[i + 1];

struct PERSON is wrong , you have already used typedef so no need to use struct . Just use PERSON *p.
To find the youngest , you code should be as follow:
#include<stdio.h>
typedef struct {
char *name;
int age;
} PERSON;
PERSON s[3] = { {"ACE", 100}, {"HEART" ,28}, {"CLOVER", 40} };
void find_young(PERSON **p) {
int i;
for (i = 0; i < ((sizeof(s)/sizeof(s[0]) -1); i++) {
if (*(p)->age > s[i+1].age) {
*p = &s[i+1];
}
}
};
void Ex1()
{
PERSON *p;
p = s;
find_young(&p);
printf("youngest man is %s.", p->name);
}
int main()
{
Ex1();
return 0;
}

Related

Function to add struct to another struct in C

so I have 3 structs here:
typedef struct {
char *name; // allocated
int commonality;
int weight;
} monster;
typedef struct {
char *name; // allocated
char *description; // allocated
double area;
int monsters;
monster **monsters; // allocated
} region;
typedef struct {
char *name; // allocated
double diameter;
int regions;
region **regions; // allocated
} planet;
I already have function:
monster *new_monster(char *name, int commonality, int weight);
I am trying to create these functions:
void add_monster_to_region(region *r, char *mname, int mcommonality, int weight);
void delete_region_from_planet(planet *p, char *rname);
This is what I have so far, but I don't believe it's right, can anyone tell me what I'm doing wrong and how I can fix it?
void add_monster_to_region(region *r, char *mname, int mcommonality, int mweight)
{
for (int i = 0; i < mcommonality; i++)
{
if (strcmp(mname, r->monsters[i]->name) == 0)
{
r->monsters[i]->name = mname;
}
}
}
Thank you
It would be very helpful to have a minimal reproducible example. It would also clarify what was meant with fully allocated NOT a reference array.
Nevertheless, here is my take on how to create a planet, two regions and how to populate the regions with monsters:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
char *name; // allocated
int commonality;
int weight;
} monster;
typedef struct {
char *name; // allocated
char *description; // allocated
double area;
int monster_count;
monster **monsters; // fully allocated, NOT a reference array
} region;
typedef struct {
char *name; // allocated
double diameter;
int region_count;
region **regions; // fully allocated, NOT a reference array
} planet;
monster *new_monster(char *name, int commonality, int weight) {
monster *new_monster = calloc(sizeof(monster), 0);
if (new_monster != NULL) {
new_monster->name = strdup(name);
if (new_monster->name == NULL) {
free(new_monster);
return NULL;
}
new_monster->commonality = commonality;
new_monster->weight = weight;
}
return new_monster;
}
void free_monster(monster *the_monster) {
if (the_monster != NULL) {
if (the_monster->name != NULL) {
free(the_monster->name);
}
free(the_monster);
}
}
void add_monster_to_region(region *r, char *mname, int mcommonality, int mweight)
{
monster *a_monster = new_monster(mname, mcommonality, mweight);
if (a_monster == NULL) return; // no memory
monster **monsters = NULL;
if (r->monsters != NULL) {
monsters = realloc(r->monsters, (r->monster_count + 1) * sizeof(monster *));
} else {
monsters = calloc(sizeof(monster *), 0);
}
if (monsters == NULL) {
free_monster(a_monster);
return; // no memory
}
r->monsters = monsters;
r->monsters[r->monster_count] = a_monster;
r->monster_count++;
}
void delete_region_from_planet(planet *p, char *rname) {
// TODO
}
int main() {
region desert = {"Desert", "Sunny and warm place.", 50.0, 0, NULL};
region ocean = {"Ocean", "Huge wet place.", 500.0, 0, NULL};
region *regions[] = {&desert, &ocean};
planet mud = {"Mud", 100.00, 2, regions};
add_monster_to_region(&desert, "Bug", 100, 100);
add_monster_to_region(&desert, "Zombie", 10, 20);
add_monster_to_region(&ocean, "Shark", 20, 40);
for (int i = 0; i < mud.region_count; i++) {
for (int j = 0; j < mud.regions[i]->monster_count; j++) {
printf("%s %d %d\n",
mud.regions[i]->monsters[j]->name,
mud.regions[i]->monsters[j]->commonality,
mud.regions[i]->monsters[j]->weight
);
}
}
// TODO: release allocated memory
return 0;
}
We can see all monsters in all regions of the defined planet:
$ gcc -Wall monsters.c
$ ./a.out
Bug 100 100
Zombie 10 20
Shark 20 40
$

Swapping struct array elements

I have difficulty applying the pass by reference and pass by value separation in structs.How can I swap the elements of the fixed size struct array as below.
struct try{
int num;
char name[10];
};
int main(){
struct try book[3];
void swapper(/********/);// <-what should be the argument of this function
}
void swapper(/********/){//swap second and third element of struct array
/*how the swap may be done?
temp=book[2];
book[2]=book[3];
temp=book[3];*/
}
There are a lot of ways to do what you're asking. One approach:
#include <stdio.h>
struct try {
int num;
char name[10];
};
void
swapper(struct try *a, int b, int c)
{
struct try tmp = a[b];
a[b] = a[c];
a[c] = tmp;
}
void
display(const struct try *t, size_t count)
{
while( count-- ){
printf("%d: %s\n", t->num, t->name);
t += 1;
}
}
int
main(void) {
struct try book[] = {
{ 1, "foo"},
{ 2, "bar"},
{ 3, "baz"}
};
display(book, sizeof book / sizeof *book);
swapper(book, 1, 2);
display(book, sizeof book / sizeof *book);
return 0;
}

Is it possible to only send one variable from a struct if that struct exists as an array?

I apologise if this seems simple, I'm still learning and I'm new to C.
I have this as my struct:
struct Game{
char id;
char name[50];
char genre[20];
char platform[15];
char company[30];
float price;
int quantity = 10;
};
And this declared as a struct array:
struct Game gList[30];
I have a function where I'm passing all of 'gList' to search through values in the gList[i].name variables.
So my question is, is it possible to send only the gList[i].name part of the struct to the function as a parameter?(ie All the 30 name values only).
No.
But you could make an array of pointers that point to the name field and pass it to the function:
char* ptr[30];
for(int i = 0; i < 30; i++)
ptr[i] = gList[i].name;
func(ptr);
No you can't. However, you can pass iterators to functions just fine. Typical pattern:
struct context { struct Game *gList; int nList; int i; }
char *iter_names(void *baton)
{
struct context *ptr = baton;
if (ptr->i == ptr->nList) return NULL;
return ptr->gList[ptr->i++].name;
}
void wants_name_array(char (*nextname)(void *), void *baton)
{
while (char *name = nextname(baton))
{
printf("%s\n", name);
/* and whatever else you are doing */
}
}
/* ... */
struct context baton = { gList, 30, 0 };
wants_name_array(iter_names, baton);
Yeah it looks kinda bad. Thankfully, gcc has an extension that makes this much better.
void wants_name_array(char (*nextname)())
{
while (char *name = nextname())
{
printf("%s\n", name);
/* and whatever else you are doing */
}
}
/* ... */
{
int i = 0;
char *nextname()
{
if (i == 30) return NULL;
return gList[i++].name;
}
wants_name_array(nextname);
}
When using this particular gcc extension, never ever return nested functions. Undefined behavior.

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

Changing a struct on the stack inside function

I am working through the Learn C the Hard Way and I am currently stuck on the extra credit exercise number 16.
I am currently trying to adapt their code and making the struct on the stack instead of the heap but my code is giving me segmentation fault and I am unsure why or how to proceed. Any advice is greatly appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Person {
char *name;
int age;
int height;
int weight;
};
void Person_create(struct Person p,char *name,int age,int height,int weight)
{
p.name = name;
p.age = age;
p.height = height;
p.weight = weight;
}
void Person_print(struct Person who)
{
printf("Name: %s\n", who.name);
printf("\tAge: %d\n", who.age);
printf("\tHeight: %d\n", who.height);
printf("\tWeight: %d\n", who.weight);
}
int main(int argc, char *argv[])
{
// make two people structures
struct Person joe;
struct Person frank;
Person_create(
joe,"Joe Alex",32,64,140);
Person_create(
frank,"Frank Blank",20,72,180);
// print them out
Person_print(joe);
Person_print(frank);
// make everyone age 20 years and print them again
joe.age += 20;
joe.height -= 2;
joe.weight += 40;
Person_print(joe);
frank.age += 20;
frank.weight += 20;
Person_print(frank);
return 0;
}
The reason your code produces errors at runtime is that C passes structs by value, meaning that the following assignments inside Person_create have no effect:
p.name = name;
p.age = age;
p.height = height;
p.weight = weight;
This makes no changes to joe and frank inside main(), leading to undefined behavior on printing, because name data member of the struct Person remains uninitialized.
In order to fix this problem, pass struct Person by pointer, and apply -> operator in place of . operator:
void Person_create(struct Person *p,char *name,int age,int height,int weight)
{
p->name = name;
p->age = age;
p->height = height;
p->weight = weight;
}
...
Person_create(&joe, "Joe Alex", 32, 64, 140);
// ^ Pass an address
It is asking for me to not use pointers or malloc, and says as advice to look into creating a struct on the stack
Your code already creates the structs on the stack. If you would like to get rid of pointers completely, change Person_create to *return` a new person, like this:
struct Person Person_create(char *name,int age,int height,int weight) {
struct Person p;
p.name = name;
p.age = age;
p.height = height;
p.weight = weight;
return p;
}
...
joe = Person_create("Joe Alex", 32, 64, 140);
Define finction Person_create the following way
void Person_create(struct Person *p, char *name, int age, int height, int weight)
{
p->name = name;
p->age = age;
p->height = height;
p->weight = weight;
}
and call it like
Person_create( &joe, "Joe Alex", 32, 64, 140 );
A more sophisticated approach is the following
#include <string.h>
#include <stdlib.h>
//...
void Person_create(struct Person *p, const char *name, int age, int height, int weight)
{
size_t n = strlen( name );
p->name = malloc( ( n + 1 ) * sizeof( char ) );
strcpy( p->name, name );
p->age = age;
p->height = height;
p->weight = weight;
}
However in this case you should remember to free the allocated memory when the object of the structure leaves its scope.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char *name;
int age;
int height;
int weight;
}Person;
void Person_print(Person who)
{
printf("Name: %s\n", who.name);
printf("\tAge: %d\n", who.age);
printf("\tHeight: %d\n", who.height);
printf("\tWeight: %d\n", who.weight);
}
int main(int argc, char *argv[])
{
Person joe= {"Joe Alex", 32, 64, 140};
Person frank={"Joe Alex", 32, 64, 140};
printf("Joe is at memory location: %p\n", &joe);
Person_print(joe);
printf("Frank is at memory location: %p\n", &frank);
Person_print(frank);
joe.age += 20;
joe.height -= 2;
joe.weight += 40;
Person_print(joe);
frank.age += 20;
frank.weight += 20;
Person_print(frank);
return 0;
}
Typedef the struct called 'Person', then you don't have to use 'Person create'.

Resources