Jak zaalokować najmniejszy wymagany obszar pamięci?

0

Witam, zwracam się do Was z moim zadaniem domowym, w trakcie którego rozwiązywania natknąłem się na kilka problemów. Pozwolę sobie wkleić treść zadania, ponieważ w miarę możliwości prosiłbym również o pomoc w interpretacji i zweryfikowanie, czy podane przeze mnie rozwiązanie pasuje do problemu. Oto treść:

Dynamiczna alokacja pamięci.

  1. Zdefiniuj parę funkcji:
    a. alokującą obszar pamięci o podanym w bajtach rozmiarze,
    b. dealokującą przekazany obszar i ustawiającą wskaźnik na NULL.
    Typ alokowanego bufora nie jest określony. Uwaga: ustal nagłówek funkcji tak, by nie zwracała ona żadnej wartości. Zaalokowany bufor musi być dostępny po wyjściu z funkcji. (2pkt)

  2. Wykorzystując funkcje z zadania 1. zaalokuj w funkcji main pewien obszar pamięci, wpisz do niego podany przez użytkownika łańcuch tekstowy (można założyć, że tekst zmieści się w obszarze), wyświetl i zwolnij przydzieloną pamięć. (2 pkt)

  3. Zdefiniuj strukturę reprezentującą element listy jednokierunkowej do przechowywania nazwisk studentów. Nie rób żadnych założeń co do maksymalnej długości nazwiska. (1pkt)

  4. Zdefiniuj funkcję dodającą na początek listy jednokierunkowej studenta o zadanym nazwisku (pamiętaj, by zaalokować najmniejszy wymagany obszar pamięci). (3 pkt)

  5. Zdefiniuj funkcję, która drukuje elementy listy studentów równocześnie je usuwając. (2pkt)

  6. W funkcji main utwórz listę jednokierunkową studentów, dodaj do niej dwa elementy, wydrukuj i usuń listę. (2pkt)

  7. Zdefiniuj funkcję wykonującą pewną operację na odpowiadających sobie elementach dwóch tablic typu float. Funkcja pobiera:
    a. dwie tablice wejściowe,
    b. jedną tablicę wyjściową,
    c. liczbę elementów do przetworzenia,
    d. wskaźnik na funkcję przekształcającą dwa elementy wejściowe w jeden element wyjściowy (argumenty i zwracana wartość typu float). (3pkt)

  8. Zdefiniuj przykładową funkcję transformującą tablice o określonym rozmiarze zainicjowane dowolnymi wartościami. Dokonaj transformacji tablic wywołując funkcję z zadania 7. (2pkt)

Jeżeli chodzi o podpunkt a z zadania 1 jest to pewniak, podpunkt b starałem zrobić się na jego podobieństwo. Zasadniczy problem pojawia się w zadaniu 4, mam wrażenie, że zadeklarowałem najmniejszy wymagany obszar, ale tak trochę na okrętkę, no i pasowałoby ten element d usunąć, mam tam zakomentowaną funkcję zwolnij(d), nie wiem gdzie ją wstawić aby było dobrze. Kolejny problem pojawia się w zadaniu 7, ponieważ nie wiem jak sprawić, aby funkcja pobierała wskaźnik na funkcję przekształcającą. Kod umieszczam poniżej, funkcji printf() jest tak dużo, ponieważ pełni to u mnie rolę wykrywacza błędów, w chwili kompilacji widzę co się dzieje, gdzie się krzaczy itd, podejrzewam, że to nieeleganckie, ale mnie pomaga. Ogólnie program działa (w środowisku codeblocks), zdaje się, że wykonuje o co proszą, ale niekoniecznie w sposób, jaki jest wymagany. Jeżeli ktokolwiek miałby jakieś wskazówki byłbym bardzo wdzięczny, w C jestem świeżakiem :) Pozdrawiam

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

//zadanie 3
typedef struct student{
char *nazwisko;
struct student *next;
}student;
//koniec zadania 3

//zadanie 1
void alloc(void**pp, int rozmiar)
{
    *pp=malloc(rozmiar);        //zwraca adres na nowy element
}

void zwolnij(void**pp)
{
    free(pp);
}
//koniec zadania 1



//zadanie 4
void dodaj_na_poczatek(student** lista, student* nowy)
{

     if((*lista)==NULL)
     {
         printf("\nDodaje pierwszego studenta na poczatek listy...\n");
        *lista = nowy;
     }
     else
     {
         printf("\nDodaje studenta na poczatek listy...\n");
         nowy->next=*lista;
         *lista=nowy;
     }
}

void dodajstudenta(student* lista, char*d)
{

    char *nazwisko=malloc(strlen(d));
    strcpy(nazwisko, d);
    //zwolnij(d);

    printf("\nDodaje studenta...\n");
    student* nowy = (student*)malloc(strlen(nazwisko));
    nowy->nazwisko=nazwisko;
    nowy->next=NULL;
    printf("\nWypisuje nazwisko dodawanego studenta: %s\n",nowy->nazwisko);
    dodaj_na_poczatek(lista,nowy);

}
//koniec zadania 4

//zadanie 5
void wypisz_liste(student** lista)
{
    printf("\nPrzystepuje do wypisania elementow...\n");
    student *temp = *lista;
    student *temp2;

     if(*lista == NULL)
     {
     printf("Brak elementow");
     }
     else
     {
     int i=1;
     while(temp!=NULL)
     {
            printf("\nWypisuje element %i: ",i);
            printf("%s", temp->nazwisko);
            temp=temp->next;
            i++;
     }
     i=1;
     while(*lista!=NULL)
     {
            printf("\nWypisuje nazwisko usuwanego studenta: %s",(*lista)->nazwisko);
            temp2=*lista;
            *lista=(*lista)->next;
            printf("\nUsuwam element %i: ",i);
            printf("%s", temp2->nazwisko);
            free(temp2);
            i++;
            getch();
     }
     }

}
//koniec zadania 5

//zadanie 8
float fun(float a, float b)
{
    int c=a*b;
    return c;
}
//koniec zadania 8

//zadanie 7
void tablice(float *a, float *b, float *c)
{
    int i,j;
    for(j=0;j<4;j++)
    {
        a[j]=j+1;
        b[j]=j+1;
    }
    for(i=0;i<sizeof(a);i++)
    {
        c[i]=fun(a[i],b[i]);
    }
}
//koniec zadania 7

int main()
{

    float a[4];
    float b[4];
    float c[4];
    tablice(a,b,c);
    int l;
    for(l=0;l<4;l++)
    {
        printf("Tablica c: %f\n",c[l]);
    }

    //zadanie 2
    char *c;
    alloc(&c,50);
    printf("Podaj lancuch tekstowy: ");
    scanf("%s",c);
    printf("Podales lancuch tekstowy: %s\n",c);
    printf("Zwalniam teraz wczesniej zadeklarowana pamiec...\n");
    zwolnij(c);
    printf("Po zwolniniu pamieci Twoj lancuch wyglada tak: %s\n",c);    //zrobilem sobie cos takiego aby miec pewnosc, ze pamiec zostala zwolniona
    //koniec zadania 2

    //zadanie 6
    student* lista = NULL;
    int i;
    char *d=malloc(100);

    for(i=0;i<2;i++)
    {
    printf("Podaj nazwisko: ");
    scanf("%s",d);
    dodajstudenta(&lista,d);
    }

    wypisz_liste(&lista);
    printf("\nWywoluje wyswietlanie po raz drugi: ");
    wypisz_liste(&lista);
    //koniec zadania 6

    return 0;
}

//uwagi zasłyszane jako wskazówki na koniec zajęć:
//strdup do wykorzystania
//to jest zle, powinna byc funkcja malloc+strlen+strcpy lub strdup

//zadanie 7 i  8 wskazowki
//maja byc przekazane 3 tablice t(float *1, float *b, float *c) - pobiera rowniez wskaznik na funkcje fun
//A+B=C, przekazac wskaznik na funkcje, ktora bedzie robic przetworzenie pary elementow tab A i B, funkcja bedzie brala 2 floaty
//float (*fun)(float, float)
//*fun ma byc wywolana na wszystkich elementach
//c[i]=(*fun)(A[i],B[i])

1

odniose sie do 4)

  1. alokujesz o 1 za malo
  2. zwolnić należy w 90% w miejscu gdzie alokujesz, bo to wtedy zmniejsza p-stwo wystąpienia błędu
  3. w tym wypadku zamiast char *d=malloc(100); lepiej dać char d[100];
  4. zamiast void dodajstudenta(student* lista, char*d) lepiej void dodajstudenta( student *lista, const char *d) to pozwoli na wywołanie dodajstudenta (&lista, "Kowalski")

Jeśli chodzi o zwalnianie pamięci, to nie czyścisz pamięci listy

w zadaniu 7 brakuje 2 argumentów w funkcji 1) ilości elementów, 2 wskaźnika na funkcje przekształcającą, podpowiedź, możesz sobie stworzyć dla czytelności typ, w tym wypadku:

typedef float (*MyEval)(float a, float b);

i uzyj tego typu

0

Dziękuje bardzo za wskazówki, starałem się zastosować, niestety typedef float (*MyEval)(float a, float b); nie udało mi się zaimplementować. Rozumiem, że ogólny zamysł na zadeklarowanie minimum pamięci jest dobry? Na ten moment po poprawkach kod wygląda tak, bardzo proszę o opinie, czy jest ok:

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

//zadanie 3
typedef struct student{
char *nazwisko;
struct student *next;
}student;
//koniec zadania 3

//zadanie 1
void alloc(void**pp, int rozmiar)
{
    *pp=malloc(rozmiar);        //zwraca adres na nowy element
}

void zwolnij(void**pp)
{
    free(pp);
}
//koniec zadania 1

//zadanie 4
void dodaj_na_poczatek(student** lista, student* nowy)
{

     if((*lista)==NULL)
     {
         printf("\nDodaje pierwszego studenta na poczatek listy...\n");
        *lista = nowy;
     }
     else
     {
         printf("\nDodaje studenta na poczatek listy...\n");
         nowy->next=*lista;
         *lista=nowy;
     }
}

void dodajstudenta(student* lista, const char *d)
{

    char *nazwisko=malloc(strlen(d));
    strcpy(nazwisko, d);
    //zwolnij(d);

    printf("\nDodaje studenta...\n");
    student* nowy = (student*)malloc(strlen(nazwisko)+1);
    nowy->nazwisko=nazwisko;
    nowy->next=NULL;
    printf("\nWypisuje nazwisko dodawanego studenta: %s\n",nowy->nazwisko);
    dodaj_na_poczatek(lista,nowy);

}
//koniec zadania 4

//zadanie 5
void wypisz_liste(student** lista)
{
    printf("\nPrzystepuje do wypisania elementow...\n");
    student *temp = *lista;
    student *temp2;

     if(*lista == NULL)
     {
     printf("Brak elementow");
     }
     else
     {
     int i=1;
     while(temp!=NULL)
     {
            printf("\nWypisuje element %i: ",i);
            printf("%s", temp->nazwisko);
            temp=temp->next;
            i++;
     }
     i=1;
     while(*lista!=NULL)
     {
            printf("\nWypisuje nazwisko usuwanego studenta: %s",(*lista)->nazwisko);
            temp2=*lista;
            *lista=(*lista)->next;
            printf("\nUsuwam element %i: ",i);
            printf("%s", temp2->nazwisko);
            free(temp2->nazwisko);
            free(temp2);
            i++;
            getch();
     }
     }

}
//koniec zadania 5

//typedef float (*fun)(float a, float b);

//zadanie 8
float fun(float a, float b)
{
    int c=a+(2*b);
    return c;
}
//koniec zadania 8

//zadanie 7
void tablice(float *a, float *b, float *c, int ilosc, float (*fun)(float a, float b))
{
    int i,j;
    for(j=0;j<ilosc;j++)
    {
        a[j]=j+1;
        b[j]=j+1;
        c[j]=(*fun)(a[j],b[j]);
    }
}
//koniec zadania 7

int main()
{

    float a[4];
    float b[4];
    float z[4];
    tablice(a,b,z,4,fun);
    int l;
    for(l=0;l<4;l++)
    {
        printf("Tablica c[%i]: %f\n",l,z[l]);
    }

    //zadanie 2
    char *c;
    alloc(&c,50);
    printf("Podaj lancuch tekstowy: ");
    scanf("%s",c);
    printf("Podales lancuch tekstowy: %s\n",c);
    printf("Zwalniam teraz wczesniej zadeklarowana pamiec...\n");
    zwolnij(c);
    printf("Po zwolniniu pamieci Twoj lancuch wyglada tak: %s\n",c);    //zrobilem sobie cos takiego aby miec pewnosc, ze pamiec zostala zwolniona
    //koniec zadania 2

    //zadanie 6
    student* lista = NULL;
    int i;
    char d[100];

    for(i=0;i<2;i++)
    {
    printf("Podaj nazwisko: ");
    scanf("%s",d);
    dodajstudenta(&lista,d);
    }

    wypisz_liste(&lista);
    printf("\nWywoluje wyswietlanie po raz drugi: ");
    wypisz_liste(&lista);
    //koniec zadania 6

    return 0;
}

0

Czas na kolejne uwagi:

  1. caly czas alokujesz o 1 element za malo....
  2. metoda zwolnij albo powinna byc inaczej wywolana, albo free winno być inaczej wywołane.
  3. napisałem, by użyć typedefa, inaczej trzeba by w inny sposób zapisać to jako argumenty - mniej czytelny jak dla mnie, a tak bedziesz miec typ myEval, gdzie sobie jako argument podasz nazwę funkcji przy wywołaniu, natomiast w deklaracji funkcji uzyjesz np jako: myEval fun
0

Poprawiłem alokowanie, free() przeniosłem na sam koniec, mam nadzieję, że spełnia swoją funkcję, natomiast niestety z tym typedefem nie potrafię sobie poradzić :( Mogę prosić o dodatkowe wskazówki?

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

//zadanie 3
typedef struct student{
char *nazwisko;
struct student *next;
}student;
//koniec zadania 3

//zadanie 1
void alloc(void**pp, int rozmiar)
{
    *pp=malloc(rozmiar);        //zwraca adres na nowy element
}

void zwolnij(void**pp)
{
    free(pp);
}
//koniec zadania 1

//zadanie 4
void dodaj_na_poczatek(student** lista, student* nowy)
{

     if((*lista)==NULL)
     {
         printf("\nDodaje pierwszego studenta na poczatek listy...\n");
        *lista = nowy;
     }
     else
     {
         printf("\nDodaje studenta na poczatek listy...\n");
         nowy->next=*lista;
         *lista=nowy;
     }
}

void dodajstudenta(student* lista, char *d)
{

    char *nazwisko=malloc(strlen(d)+1);
    strcpy(nazwisko, d);
    printf("\nDodaje studenta...\n");
    student* nowy = (student*)malloc(strlen(nazwisko)+1);
    nowy->nazwisko=nazwisko;
    nowy->next=NULL;
    printf("\nWypisuje nazwisko dodawanego studenta: %s\n",nowy->nazwisko);
    dodaj_na_poczatek(lista,nowy);


}
//koniec zadania 4

//zadanie 5
void wypisz_liste(student** lista)
{
    printf("\nPrzystepuje do wypisania elementow...\n");
    student *temp = *lista;
    student *temp2;

     if(*lista == NULL)
     {
     printf("Brak elementow");
     }
     else
     {
     int i=1;
     while(temp!=NULL)
     {
            printf("\nWypisuje element %i: ",i);
            printf("%s", temp->nazwisko);
            temp=temp->next;
            i++;
     }
     i=1;
     while(*lista!=NULL)
     {
            printf("\nWypisuje nazwisko usuwanego studenta: %s",(*lista)->nazwisko);
            temp2=*lista;
            *lista=(*lista)->next;
            printf("\nUsuwam element %i: ",i);
            printf("%s", temp2->nazwisko);
            free(temp2->nazwisko);
            free(temp2);
            i++;
            getch();
     }
     }

}
//koniec zadania 5

typedef float (*MyEval)(float a, float b);

//zadanie 8
MyEval fun(float a, float b)
{
    int c=a+b;
    return c;
}
//koniec zadania 8

//zadanie 7
void tablice(float *a, float *b, float *c, int ilosc, MyEval *fun)
{
    int i,j;
    for(j=0;j<ilosc;j++)
    {
        a[j]=j+1;
        b[j]=j+1;
        c[j]=(*fun)(a[j],b[j]);
    }
}
//koniec zadania 7

int main()
{

    float a[4];
    float b[4];
    float z[4];
    tablice(a,b,z,4,fun);
    int l;
    for(l=0;l<4;l++)
    {
        printf("Tablica c[%i]: %f\n",l,z[l]);
    }

    //zadanie 2
    char *c;
    alloc(&c,50);
    printf("Podaj lancuch tekstowy: ");
    scanf("%s",c);
    printf("Podales lancuch tekstowy: %s\n",c);
    printf("Zwalniam teraz wczesniej zadeklarowana pamiec...\n");
    zwolnij(c);
    printf("Po zwolniniu pamieci Twoj lancuch wyglada tak: %s\n",c);    //zrobilem sobie cos takiego aby miec pewnosc, ze pamiec zostala zwolniona
    //koniec zadania 2

    //zadanie 6
    student* lista = NULL;
    int i;
    char *d=malloc(100);

    for(i=0;i<2;i++)
    {
    printf("Podaj nazwisko: ");
    scanf("%s",d);
    dodajstudenta(&lista,d);
    }
    free(d);
    printf("\n(d): %s\n",d);
    wypisz_liste(&lista);
    printf("\nWywoluje wyswietlanie po raz drugi: ");
    wypisz_liste(&lista);
    //koniec zadania 6

    return 0;
}

0

zwalniasz d, a potem jej uzywasz?
powtarzam, masz zle napisana funkcje zwolnij
nie zwalniasz listy.
kolejny blad fun zeby byla typu myEval musi zwracac float... heh chyba masz duże braki

0

d używałem na sam koniec aby sprawdzić, co się tam znajduje i mieć pewność, że jest wyczyszczone, nic więcej :)
czy w funkcji zwolnij wystarczy zmodyfikować tyle?

void zwolnij(void**pp)
{
   free(*pp);
}

Tak jak wspomniałem w C jestem świeżakiem, braki mam duże, nie da się ukryć

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