Tablica wskaźników struktur – kod do poprawy

0

Cześć, przypadkiem usunąłem cały tekst z postu więc piszę jeszcze raz.. Dostałem takie zdanie do zrobienia i stworzyłem taki kod ale on nie działa . Szukam pomocy
photo_2018-11-30_13-56-08 (1).jpg


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

struct person {

    char surname[50];
    unsigned int wiek;
    int iloscPotomkow;
    struct potomek* potomkowie[];
};

struct potomek {
    char surname[50];
    unsigned int wiek;
};

void zrobPotomka(struct person** person,int idx)
{
    struct potomek** potomek;
    potomek[idx - 1] = (struct person*)malloc(sizeof(struct person));
    potomek[idx - 1]->wiek = person->wiek;
    memcpy(potomek[idx - 1]->surname, persons[idx]->surname, persons[idx]->surname.sizeof() / "a".sizeof());
    person->iloscPotomkow + ;
    person->potomkowie[idx - 1] = potomek;
    freePersons(person[idx]);
};

bool ifPersonExist(int i, struct person** person)
{

    if (persons[i] == NULL) {
        return true;
    }
    else
        return false;
}

void printAPerson(int i, struct person* person)
{
    printf("Person(%d): %s, level %d\n", i, person->name, person->level);
}

void printPersons(struct person** persons, int num)
{
    for (int i = 0; i < num; i++) {
        if (persons[i] == NULL) {
            continue;
        }
        printAPerson(i, persons[i]);
    }
}

void createPersons(struct person** persons, int idx, const char* surname[], unsigned int level, int surnameLong)
{
    persons[idx] = (struct person*)malloc(sizeof(struct person));
    persons[idx]->level = level;
    memcpy(persons[idx]->surname, surname, surnameLong);
}

void freePersons(struct person** persons, int num)
{
    //Najpierw zwolnij pamiec dla wszystkich bohaterow
    for (int i = 0; i < num; i++) {
        if (persons[i] == NULL) {
            continue;
        }
        free(persons[i]);
    }

    //teraz usun pamiec dla tablicy
    free(persons);
}

int main()
{

    struct person** persons;

    char w;
    scanf("%c", &w);

    char surname[100];
    int age;
    int idx,idxMax=0;
    int size;

    printf("podaj ile chcesz stworzyć osób");
    scanf(&size);
    int tabOfIdx[size];
    while (i < size) {
        i++;
        switch (w) {
        case 'a':

            printf("podaj indeks do utowrzenia osoby  ");
            scanf("%d", idx);
            if (idx>idxMax){
                idxMax=idx;
            }
            if (ifPersonExist(idx)) {
                printf("podaj prosze nazwisko oraz wiek");
                scanf(&surname, &age);
                createPersons(person, idx, surname, age, surname.sizeof() / surname[0]);
            }
            else
                printf("osoba o podanym in...");
        case 'c':
    while (i < idxMax) {
          if (ifPersonExist(idx)) {
            zrobPotomka(persons,i++);
          }}
            break;
        case 'p':
            printPersons(persons, size);
            break;
        default:
        }
    }
    return 0;
}

2
  1. zdefiniuj "nie działa"
  2. czy przypadkiem "tablica potomków"nie jest po prostu "tablicą osób" będących potomkiem danej osoby? W sensie potrzebna ci ta dodatkowa struktura?
  3. Gorsze od pisania kodu po polsku, jest pisanie kodu po polsku i po angielsku. Pisz tylko po angielsku, wszystko! Jak pójdziesz do pracy i zobaczysz komentarze albo kod napisane po portugalsku albo słowacku to zrozumiesz czemu.
3

Pan profesor ma opory przed umieszczaniem zadań jako tekstu? :​/

Poprawiłem trochę czytelność, ale wciąż słabo

0
MarekR22 napisał(a):
  1. zdefiniuj "nie działa"
  2. czy przypadkiem "tablica potomków"nie jest po prostu "tablicą osób" będących potomkiem danej osoby? W sensie potrzebna ci ta dodatkowa struktura?
  3. Gorsze od pisania kodu po polsku, jest pisanie kodu po polsku i po angielsku. Pisz tylko po angielsku, wszystko! Jak pójdziesz do pracy i zobaczysz komentarze albo kod napisane po portugalsku albo słowacku to zrozumiesz czemu.

Wybacz za polsko-angielski wiem katastrofa , 1 nie rozumiem jak mam stworzyć tych potomków na bazie tego jednego, poprawiłem trochę kod , zmieniłem to co mówiłeś ale nie wiem jak wypisać dobrze te wszystkie indeksy skoro mogę podać dowolny a maks ma być dziesięć

1

Popatrz na opis ostatniej komendy z zadania (tu bym wkleił odpowiedni fragment tekstu jakby się dało :P).
Potomek to jest to samo co Osoba! Potomek to po prostu określenie relacji miedzy dwiema osobami!

0
MarekR22 napisał(a):

Popatrz na opis ostatniej komendy z zadania (tu bym wkleił odpowiedni fragment tekstu jakby się dało :P).
Potomek to jest to samo co Osoba! Potomek to po prostu określenie relacji miedzy dwiema osobami!

czyli zrobić w potomku
int iloscPotomkow;
struct person* persons[];

a w osoby co ?

0

Ależ nie.
Po prostu rozszerzasz strukturę Osoba:

struct Osoba
{
//to co miała dotychczas
    unsigned int descendantsCount;//może być 0
    Osoba *descendants;//tablica potomków, albo NULL jak nie ma potomków
};
0
MasterBLB napisał(a):

Ależ nie.
Po prostu rozszerzasz strukturę Osoba:

struct Osoba
{
//to co miała dotychczas
    unsigned int descendantsCount;//może być 0
    Osoba *descendants;//tablica potomków, albo NULL jak nie ma potomków
};
  

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


#define allocPersons2(persons, size)                                       \
{                                                                       \
    persons = (struct person**)malloc((sizeof(struct person*) * size));      \
    for (int i=0; i<size; i++) {                                        \
        persons[i] = NULL;                                               \
    }                                                                   \
}

struct person {

    char surname[50];
    unsigned int wiek;
    struct    person* persons;
     unsigned int descendantsCount
};


struct potomek {
    char surname[50];
    unsigned int wiek;
};
 void allocPersons(struct person** persons, int size)
{
    persons = (struct persons**)malloc((sizeof(struct persons*) * size));
    for (int i=0; i<size; i++) {
        persons[i] = NULL;
    }
}


void zrobPotomka(struct person* person,int idx)
{
    char surnameArray[45];

    strcpy(surnameArray,person->surname );



    person->persons[idx - 1] = (struct person*)malloc(sizeof(struct person));
    person->persons[idx - 1]->wiek = person->wiek;
    memcpy(persons[idx - 1]->surname, person->surname, sizeof(surnameArray)/sizeof(surnameArray[0]));
    person->descendantsCount ++ ;

    freePersons(person[idx]);
};

bool ifPersonDoesntExist( struct person** persons,int i )
{

        if (persons[i] == NULL) {
             return true;
        }
        else
            return false;

}

void printAPerson(int i, struct person* person)
{
    printf("Person(%d): %s, wiek %d\n", i, person->surname, person->wiek);
}

void printPersons(struct person** persons, int num)
{
    for (int i = 0; i < num; i++) {
        if (persons[i] == NULL) {
            continue;
        }
        printAPerson(i, persons[i]);
    }
}

void createPersons(struct person** persons, int idx, const char surname[25], unsigned int wiek, int surnameLong)
{
    persons[idx] = (struct person*)malloc(sizeof(struct person));
    persons[idx]->wiek = wiek;
    memcpy(persons[idx]->surname, surname, surnameLong);
}

void freePersons(struct person** persons, int num)
{

    for (int i = 0; i < num; i++) {
        if (persons[i] == NULL) {
            continue;
        }
        free(persons[i]);
    }

    //teraz usun pamiec dla tablicy
    free(persons);
}

int main()
{

    struct person** persons;

    char w;


    char surname[100];
    int age;

    int size,i=0;

 int idx,idxArray[size];
allocPersons(persons,size);
    printf("podaj ile chcesz stworzyć osob");
    scanf("%d", &size);

    int tabOfIdx[size];
    allocPersons(persons,size);
    while (i < size) {

      printf("podaj jaką opcje wybierasz \n");
     printf("a --- utwórz strukture pod wybranym indeksem \n");
     printf("p --- wypisz wszystkie dane z tablicy \n");
     printf("c --- utworz potomkow na bazie osoby \n");
     scanf("%c", &w);

        switch (w) {
        case 'a':

            printf("podaj indeks do utowrzenia osoby  ");
            scanf("%d", &idx);
            idxArray[i]=idx;

            if (ifPersonDoesntExist(persons,idx)) {
                printf("podaj prosze nazwisko");

                scanf("%s",&surname);

                 printf("podaj prosze  oraz wiek");
                scanf("%d",&age);
                createPersons(persons, idx, surname, age, sizeof(surname)/sizeof(surname[0]));
                 i++;
            }
            else
                printf("osoba o podanym indeksie istnieje");
                break;
        case 'c':


    for (int k=0 ; k< sizeof(idxArray)/sizeof(idxArray[0]); k++) {
          if (ifPersonDoesntExist(persons,idx)) {
            zrobPotomka(persons,k);
          }
          }




            break;
        case 'p':
            for (int k=0 ; k< sizeof(idxArray)/sizeof(idxArray[0]); k++) {
          if (ifPersonDoesntExist(persons,idx)) {
           printAPerson(idx,persons[i]);
          }
            }
            break;
        default:
             printf("dowidzenia");
        }
    }
    return 0;
}

czy o to ci chodziło ? bo teraz nie moge zrobić Potomka

2
The Best napisał(a):

(...) bo teraz nie moge zrobić Potomka


( ͡° ͜ʖ ͡ °)

A tak na serio - nie potrzebujesz klasy Potomek, po prostu zmodyfikuj zrobPotomka():

void zrobPotomka(Osoba &parent, unsigned int howManyDescendants)
{
    parent.descendantsCount = howManyDescendants;    
    parent.descendants = (Osoba*) malloc(howManyDescendants * sizeof(Osoba));//nie używałem malloc od wieków, mogą być drobne błędy

    for (int offset = 0; offset < howManyDescendants; offset++)
    {
         Osoba *descendant = parent.descendants + offset;
         descendant->surname = parent.surname;//tu uproszczenie kopiowania nazwiska
         descendant->age = 0;//w końcu dopiero co utworzony ^^
    }
}
0

A tak na serio - nie potrzebujesz klasy Potomek, po prostu zmodyfikuj zrobPotomka():

void zrobPotomka(Osoba &parent, int howManyDescendants)
{
    parent.descendantsCount = howManyDescendants;
    parent.descendants = new Osoba[howManyDescendants]; //skoro to C to przerób to na użycie malloc

    for (int offset = 0; offset < howManyDescendants; offset++)
    {
         Osoba *descendant = parent.*(descendants + offset);
         descendant->surname = parent.surname;//tu uproszczenie kopiowania nazwiska
         descendant->age = 0;//w końcu dopiero co utworzony ^^
    }
}

no ale w c właśnie to próbuje zrobić tyle że nie na wszystkich osobach a na pojedynczej i mi nie wychodzi

0

No i robisz na pojedynczej - tylko Osobie przesłanej do zrobPotomka jako parent tworzysz X Osób potomnych.

1

Bracie @The Best z tymi potomkami możesz postąpić na 2 sposoby:

  • albo utworzyć całkiem nowych przy pomocy zrobPotomka(), wtedy podajesz rodzica dla którego mają być zrobieni, i ilu ich będzie
  • albo stworzyć nową funkcję przypiszPotomka(Osoba &parent, Osoba *potomek) która już istniejący obiekt klasy Osoba dopisze do rodzica. Niestety, rzecz się komplikuje jak ten rodzic ma już potomków - trzeba będzie skopiować tablicę potomków i powiększyć ją o jeden, a na końcu skopiować zawartość wskaźnika *potomek na koniec nowej tablicy, a starą zwolnić.
0

a jesteś pewny że w c tak to powinno być ?
void zrobPotomka(person &parent, unsigned int howManyDescendants)
?

2

O Swarogu, jaki ten C upierdliwy...słuszne uwagi Bracie, za wiele C++ dałem do rozwiązania powyżej.
Poprawione do postaci kompilowalnej:

#include <stdio.h>

struct Person
{
    struct Person *descendants;
    unsigned int descendantsCount;
};

void makeDescendant(struct Person *parent, unsigned int howMany)
{
    parent->descendants = (struct Person*) malloc (howMany * sizeof(struct Person));
    parent->descendantsCount = howMany;
}

int main()
{
    struct Person JanKowalski;
    
    makeDescendant(&JanKowalski, 2);

    return 0;
}

https://onlinegdb.com/HymjwrUkE

0


void zrobPotomka(struct person** parent, unsigned int idx,int size)
{
    parent[0]->descendantsCount = parent[0]->descendantsCount+1;// z polecenia wyniki ze potomkowie beda tylko dla indeksu 1 czyli 0
     parent[0]->descendants = (struct persons**)malloc((sizeof(struct persons*) * size)); // tworze tablice struktur dla potomków o rozmiarze podanym przez użytkownika
    struct person* descendant;
     descendant = (struct person*)malloc(sizeof(struct person));

     strcpy(descendant->surname , parent[0]->surname);//tu uproszczenie kopiowania nazwiska
         descendant->wiek =  parent[0]->wiek;//w końcu dopiero co utworzony ^^


    freePersons(parent[idx]);
};

dobra zrobiłem to tak i na razie się kompiluje

0

bool ifPersonDoesntExist( struct person** persons,int i )
{

    if (persons[i] == NULL)
    {
        return true;
    }
    else
        return false;

}

Za każdym razem zwraca że osoba istnieje , dlaczego

Poddaje się z tym c, pętla na switchu wykonuje się dwa razy, program się nie kompiluje po tym jak się wysypie i wyrzuca Process returned -1073741571 (0xC00000FD)

0

https://onlinegdb.com/ryOmML8kN

wybacz że za pierwszym razem dałem bez wybrania języka

1

Trochę za wiele masz tu nawalone w maina(), pozwoliłem sobie uprościć. Generalnie, niepotrzebnie tu się babrasz z jakimiś indeksami, wskaźnikami do wskaźników itd.
Patrz Bracie, taki prosty zapis działa:

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

struct Person
{
    char surname[50];
    unsigned int age;
    
    struct Person *descendants;
    unsigned int descendantsCount;
};

void zrobPotomka(struct Person *parent, unsigned int howMany)
{
    parent->descendants = (struct Person*) malloc(howMany * sizeof(struct Person));
    parent->descendantsCount = howMany;
    
    for (int offset = 0; offset < howMany; offset++)
    {
        struct Person *currentDescendant = parent->descendants + offset;
        strcpy(currentDescendant->surname, parent->surname);
        currentDescendant->age = 0;
    }
}

void printPersonData(struct Person *person)
{
    printf("Nazwisko: %s, Wiek: %d, ilość potomków: %d \n", person->surname, person->age, person->descendantsCount);
    //printf("Wiek: %d, ilość potomków: %d \n", person->age, person->descendantsCount);
    for (int cnt = 0; cnt < person->descendantsCount; cnt++)
    {
        printf("Potomek %d:", cnt + 1);
        struct Person *descendant = person->descendants + cnt;
        printPersonData(descendant);
    }
}

int main()
{
    struct Person JanKowalski;
    JanKowalski.age = 45;
    strcpy(&JanKowalski.surname, "Kowalski");
    JanKowalski.descendantsCount = 0;
    
    printPersonData(&JanKowalski);
    
    zrobPotomka(&JanKowalski, 2);
    
    printPersonData(&JanKowalski);

    return 0;
}

https://onlinegdb.com/Bynu2LLk4

0
MasterBLB napisał(a):

https://onlinegdb.com/Bynu2LLk4

To by było zbyt proste i logiczne :P
Cały myk polega na tym że użytkownik robi tablice na tyle osób ile mu się podoba i przy każdej wybiera jej index , przy czym nie może dwa razy wybrać tego samego.
ma 3 opcje - switch
a utwórz osobe o wpisanym nazwisku i wieku na wybranym indeksie
p - wypisz wszystkie osoby i ich dane
c- wszystkie osoby o indeksie większym ustaw jako potomków osoby o indeksie 1 oraz zwolnij pamiec ponich z tablicy osób

1

No to na dzień dobry trzeba użytkownika pytać, na ile osób ma być ta wstępna tablica, nie ma innej opcji.
Jak już wiadomo, ile osób będzie max to zastosować przydział pamięci mallocem tak jak jest w zrobPotomka.

Co do zabraniania nadpisywania raz podanych indeksów, hm....chyba tutaj musisz stworzyć tablicę char indexesUsed[ileOsób] zainicjalizowaną zerami, i jak użytkownik będzie chciał wpisać osobę to sprawdzasz, czy podawany index w indexesUsed == 0. Jeśli tak to pozwalasz na akcję, a wartość w indexesUsed[index] przestawiasz na nie-zero.

1 użytkowników online, w tym zalogowanych: 0, gości: 1