-2

so at first, I didnt know I had to use struct so I failed miserably and had to change my whole code but now it can't print anything :(

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct p {
    char* name;
    int year_of_birth;
    char* sex;
    struct p* mother;
    struct p* father;
    struct p* significant_other;
    struct p** children;


}typedef Person;

this is where I define my structure

Person* person_constructor(char *name, int year_of_birth, char *sex);
Person* birth(char *name, int year_of_birth, char *sex, Person *mother);

void display_person(Person* p);
void marry_them(Person *p1, Person *p2);
void display_family(Person* family[], int n);
Person* sibling(Person p, int print);

here are my function definitions

int main() {
    Person* p1 = person_constructor("Abbas", 1970, "male");
    Person* p2 = person_constructor("Sidika", 1970, "female");
    marry_them(p1, p2);
    Person* p3 = person_constructor("Pinar", 1990, "female");
    Person* p4 = birth("Siamak", 1990, "male", p2);
    marry_them(p3, p4);
    Person* p5 = birth("Guzide", 1990, "female", p2);
    Person* p6 = person_constructor("Fatih", 1990, "male");
    marry_them(p5, p6);
    Person* p7 = birth("Berkecan", 2010, "male", p3);
    Person* p8 = birth("Ekinsu", 2010, "female", p3);
    Person* p9 = birth("Canim", 2010, "female", p5);



    display_person(p1);

my main where I summon people, marry them etc and most important part,

return 0;
}
Person* person_constructor(char *name, int year_of_birth, char *sex)
{
    Person *p = calloc(1,sizeof(*p));
    strcpy(p->name, name);
    p->year_of_birth = year_of_birth;
    strcpy(p->sex, sex);


    return p;
}



void display_person(Person* p)
{

    printf("================\n");
    printf("Name   : %s \n",p->name);
    printf("Sex    : %s \n",p->sex);
    printf("Year   : %d \n",p->year_of_birth);
    if (strcmp(p->father,"") == 0){
        printf("Father : NA \n");
    }
    else {
        printf("Father : %s \n", p->father);
    }
    if (strcmp(p->mother,"") == 0){
        printf("Mother : NA \n");
    }
    else {
        printf("Mother : %s \n", p->mother);
    }
    if (strcmp((const char *) p->significant_other, "") == 0){
        printf("Sig.O  : NA \n");
    }
    else {
        printf("Sig.O  : %s \n", p->significant_other);
    }
    if (strcmp(p->children,"") == 0){
        printf("Child 1 : NA \n");
    }
    else {
        printf("Child 1 : %s \n", p->children[0]);
    }
    if (strcmp(p->children,"") == 0){
        printf("Child 2 : NA \n");
    }
    else {
        printf("Child 2 : %s \n", p->children[1]);
    }
}

void marry_them(Person *p1, Person *p2)
{
    strcpy(p1->significant_other, p2->name);
    strcpy(p2->significant_other, p1->name);

}
Person* birth(char *name, int year_of_birth, char *sex, Person *mother) {
    Person *p = person_constructor(name, year_of_birth, sex);
    strcpy(p->mother, mother->name);
    strcpy(p->father, mother->significant_other);

    return p;
}
void display_family(Person* family[], int n)
{
for (int i = 0;i<n;i++)
{
   display_person(family[i]);
}
}
Person* sibling(Person p, int print)
{


}

these are my functions, I wrote them for char mother[20] kind of code instead of struct mother and I am tangled. I can't print out human info, it should look like this:

================ 
Name   : Steven
Sex    : male 
Year   : 1970 
Father : NA 
Mother : NA 
Sig.O  : Eva
Child 1: Laura
Child 2: Alice 
================ 

above code is just representation without names I used in my main codes, just so you get what it is meant to do. Thanks in advance!

  • 1
    Review `strcpy(p->name, name);`. When this is called, `p->name` is `NULL`. – chux - Reinstate Monica Nov 17 '19 at 19:45
  • @chux-ReinstateMonica why is it NULL, shouldn't it take the name of abbas when I first summon person_constructor ? – ExperiencedSoup Nov 17 '19 at 19:47
  • 1
    @chux-ReinstateMonica I turned it into p->name = name; and it looks like it works but there are still so much flaws – ExperiencedSoup Nov 17 '19 at 19:48
  • `p = calloc(1,sizeof(*p));` set `p->name` to 0. The happens before `strcpy()`. `p->name` needs some allocated memory if you want distinctive names.. Try `p->name = strdup(name);` – chux - Reinstate Monica Nov 17 '19 at 19:49
  • Something wrong with 'children'. I could not find anywhere they are set, but the code still print them. The are declared as struct p**, but are used as string. Consider removing all cast like 'const char *)` to let the compiler tell you about type mismatches – dash-o Nov 17 '19 at 19:50
  • @dash-o I removed all my const char* like stuff and now it prints name birth and sex pretty decently but wont print out significant other – ExperiencedSoup Nov 17 '19 at 19:55
  • 2
    Does this answer your question? [Dynamically allocate C struct?](https://stackoverflow.com/questions/1979879/dynamically-allocate-c-struct) – Andreas is moving to Codidact Jul 13 '20 at 01:15

3 Answers3

0

Does your code compile on your machine, I tried and it does not on my machine. You need to fix the code first in order to compile it, like change this

Person *p = calloc(1,sizeof(*p));

to

Person *p = (Person *)calloc(1, sizeof(Person));

and also change strcmp(p->father, "") to strcmp(p->father->name, "")

p->father is not a string and instead a struct. You cannot compare a struct with a string.

Similarly do for the mother and children.

  • I can suggest more changes so that your code compiles well. Try yourself and let me know if further help needed. – Shivam Jindal Nov 17 '19 at 19:58
  • I removed all strcpy and replace them with ones like p->year_of_birth = year_of_birth; It still doesn't work doe – ExperiencedSoup Nov 17 '19 at 20:11
  • The `calloc` statements are the same, but the 2nd one with the superfluous cast is way harder to maintain and read, (though C++ requires it.) `p->father` is not a valid pointer, then `p->father->name` is going to crash. – Neil Nov 17 '19 at 23:34
0

Probably there is an issue in the person_constructor function. Try doing this:

Person* person_constructor(char *name, int year_of_birth, char *sex)
{
    Person *p = (Person *)calloc(1, sizeof(Person));
    strcpy(p->name, name);
    p->year_of_birth = year_of_birth;
    strcpy(p->sex, sex);
    return p;
}

For the display_person function the parents are not strings, but pointers, so they are null or structs:

void display_person(Person* p) {
    printf("================\n");
    printf("Name   : %s \n",p->name);
    printf("Sex    : %s \n",p->sex);
    printf("Year   : %d \n",p->year_of_birth);

    printf("Father : %s \n", p->father == null ? "N/A" : p->father->name);
    printf("Mother : %s \n", p->mother== null ? "N/A" : p->mother->name);

    printf("Sig.O  : %s \n", p->significant_other== null ? "N/A" : p->significant_other->name);
    printf("Child 1: %s \n", p->children[0]== null ? "N/A" : p->children[0]->name);

    //Others here
}
Dirant
  • 9
  • 1
  • 2
0

As it stands, one has defined:

Person

Then one uses calloc to get an instance of this:

calloc Person

Which is fine, but notice that the pointers are not valid. strcpy will on an invalid pointer is undefined behaviour. One could p->name = name, that would result in the compiler pointing name to the name parameter:

p->name = name

Since one is using static constant names, the name will never disappear and not be changed. This is good as long as one is controlling where the name comes from. Suppose name was input to a temporary char * before being passed to person_constructor; one would only have a defined name as long as the underlying temporary variable were present. A common way to avoid this is copying.

Person *p;
char *pname;
size_t name_len = strlen(name);
p = calloc(1, sizeof *p + name_len + 1);
if(!p) return 0;
pname = (char *)(p + 1);
strcpy(name, pname);
p->name = pname;

This copies name the parameter into the newly-formed p after the space where p is, (since one allocated that space.) The other option is to allocate a fixed maximum number of characters name[200] and copy the name directly in, (be careful that strcpy does not cause overflow.)

strcmp(p->father,""), is passing struct p when it expects const char * (see documentation.) The strcmp function knows nothing about struct p, but will happily return extraneous values or crash. I would suggest setting the father explicitly to 0 (NULL) in the constructor, (this is not guaranteed to be all-bytes-zero,) then one can printf("Father : %s \n", p->father ? p->father->name : "N/A");.

The same thing with children, except birth causes the array to grow. If it's a dynamic array, one will need to realloc something. The alternative is to allocate a fixed maximum number of children.

Neil
  • 1,767
  • 2
  • 16
  • 22