Strutura i talbica oraz dynamiczna alokacja pamięci

0

Robię mały programik, co symuluje Lotto (losowania ;p)
Mam strukturę

struct sDrawResults{
    unsigned int ID; // numer losowania
    unsigned int Number; //wylosowana liczba
};

i 6 elementową tablicę struktur

sDrawResults DrawResults[6];

teraz chciałbym dynamicznie alokować wielkość tej tablicy (niekoniecznie 6 liczb, ale czasami 2 a czasami 200)

więc tak do tego podchodzę:

int rozmiar = 6; // tu będę wpisywał rozmiar
sDrawResults *DrawResults; // tu tworzę wskaźnik typu mojej struktury
DrawResults = (int*)malloc(rozmiar*sizeof(*DrawResults)); // tu alokuję ilość pamięci w zależności od rozmiaru

i teraz nie wiem co dalej i co jest źle. Kompilator wywala błąd "DrawResultats' does not name a type

1

W jednym losowaniu idzie 6 liczb, więc po kiego ci Id na każdą liczbę?
Zrób sensowna strukturę: typedef struct { unsigned Id; unsigned Numbers[6]; } LottoResult;
Po czym przydzielaj: LottoResult *data=malloc(count*sizeof(LottoResult));
Numery są małe więc ma sens trzymać liczby w: unsigned char Numbers[6];
A jeżeli zrozumiesz operacje bitowe i nie obchodzi cię kolejność w której ta 6-tka została wylosowana to można trzymać liczby w: long long Numbers;
np jeżeli wylosowano liczby 12,17,19,33,39,47 to Numbers=(1LL<<12)|(1LL<<17)|(1LL<<19)|(1LL<<33)|(1LL<<39)|(1LL<<47);

0
_13th_Dragon napisał(a):

W jednym losowaniu idzie 6 liczb, więc po kiego ci Id na każdą liczbę?

Będę potem robił sortowanie. To na zajęcia w szkole, dlatego taka forma

Zrób sensowna strukturę: typedef struct { unsigned Id; unsigned Numbers[6]; } LottoResult;
Po czym przydzielaj: LottoResult *data=malloc(count*sizeof(LottoResult));
Numery są małe więc ma sens trzymać liczby w: unsigned char Numbers[6];

Na razie chciałbym wiedzieć jak sprawę rozwiązać na takiej strukturze jaką podałem :) to dla ćwiczenia, więc profesjonalistów proszę o nie obruszanie się, że coś nie jest optymalne.

A jeżeli zrozumiesz operacje bitowe i nie obchodzi cię kolejność w której ta 6-tka została wylosowana to można trzymać liczby w: long long Numbers;
np jeżeli wylosowano liczby 12,17,19,33,39,47 to Numbers=(1LL<<12)|(1LL<<17)|(1LL<<19)|(1LL<<33)|(1LL<<39)|(1LL<<47);

Na razie operacje bitowe mnie nie interesują ;)

0

Może chociaż ktośby mi pokazał, jak do takiej struktury

struct sDrawResults{
    unsigned int ID;
    unsigned int Number;
};

sDrawResults DrawResults[6]; // tożsame z sDrawResults *DrawResults; jak dobrze rozumiem?

stworzyć dynamiczną tablicę struktur (nie wiem czy się dobrze wyrażam). Po prostu ta pojemność nie zawsze będzie 6. Chcę, by to użytkownik decydował o tym, dlatego chcę to zrobić dynamicznie. To jest zadanie na zajęcia, więc może i da się to zrobić inaczej, ale ja chcę potrenować struktury i dynamiczne alokowanie pamieć. Na razie próbuję i nic mi nie wychodzi.

Może wkleję co mam tak dla jasności

#include <cstdio>
#include <stdlib.h>
#include <ctime>

//Funkcja zwraca liczbę pseudolosową z przedziału <min, max>
int RandRange(int min, int max)
{
    return min + rand() % (1 + max - min);
}

int rozmiar = 6; // zmienna globalna - ile liczb losować

struct sDrawResults{
    unsigned int ID;
    unsigned int Number;
};



void DrawNumbers(int first, int last)
{

//tutaj tworzę nową tablicę typu struktura sDrawResults o nazwie DrawResults.
//sDrawResults DrawResults[6]; //  to ma być dynamiczne. Możemy losować tyle ile zadany w 'rozmiar'
sDrawResults *DrawResults; // to samo co na górze

DrawResults = (int*)malloc(rozmiar*sizeof(rozmiar)); // tutaj nie wiem jak to zrobić

    for (int i=0; i<6; i++)
    {
        DrawResults[i].ID = RandRange(first, last);
        DrawResults[i].Number = i+1;

        for (int j=0; j<i; j++)
        {
            if (DrawResults[i].ID == DrawResults[j].ID)
            {
                i = i-1;
                break;
            }
        }


//        printf("Wynik: %d \n", DrawResults[i].ID);
//        printf("ID losowania: %d \n\n", i, DrawResults[i].Number);
    }
}

void PrintDrawnNumbers()
{
    printf("Wylosowano następujące liczby: \n");
    printf("ID  | Numer liczby \n");
    printf("--------------------\n");

        for (int i=0; i<6; i++)
    {
        printf("%3d | %3d\n", DrawResults[i].Number, DrawResults[i].ID);
    }
}

int main()
{
    srand(time(NULL));
    DrawNumbers(1,49);

    PrintDrawnNumbers();

    return 0;
}
0

Mniej więcej taki schemat powinien być (na szybko pisane, więc moga być jakies literówki)

 

struct sDrawResults *DrawNumbers(int first, int last, size_t asize)
{
    struct sDrawResults *DrawResults; // to samo co na górze
 
    DrawResults = (int*)malloc(asize*sizeof(struct sDrawResults));
....
   return DrawResults;
}
...
int main()
{
    srand(time(NULL));
... 
    struct sDrawResults *myDrawResults= DrawNumbers(1,49, ilosc);
 
    PrintDrawnNumbers(myDrawResults);

    free(myDrawResults);
 
    return 0;
}
0

Więc zrobiłem ten program i chyba działa.
Jeżeli ktoś ogarnięty mógłby rzucić okiem i sprawdzić, czy dobrze użyłem funkcji malloc, czy dobrze używam stryktury i wskaźników. Szczególnie dlaczego w 17 linijce nie mogę tak zadeklarować wskaźnika(wywala błąd). Oraz czy w komentarzach dobrze to sobie wszystko tłumaczę.
Za wszelką pomoc będę bardzo wdzięczny.
Oraz przypominam, że to program na zajęcia, więc nie musi być optymalny ;)

#include <cstdio>
#include <stdlib.h>
#include <ctime>

//Funkcja zwraca liczbę pseudolosową z przedziału <min, max>
int RandRange(int min, int max)
{
    return min + rand() % (1 + max - min);
}

int rozmiar = 10; // zmienna globalna - ile liczb wylosować

int *wskRozmiar = &rozmiar;

        /* czemu nie może być: ?

        int *wsk = NULL;
        wsk = &rozmiar; // błąd: 'wsk' doesn't name a type

        */

// tworzę strukturę
typedef struct sDrawResults{
    unsigned int ID;
    unsigned int Number;
};

//tutaj tworzę nową tablicę typu struktura sDrawResults o nazwie DrawResults.
    // sDrawResults DrawResults[rozmiar]; na dole inicjuje coś podobnego
sDrawResults *DrawResults = NULL;

void DrawNumbers(int first, int last, int rozmiar)
{

DrawResults = (sDrawResults*) realloc(DrawResults, rozmiar * sizeof(sDrawResults)); // alokuję pamięć 

    for (int i=0; i<*wskRozmiar; i++)
    {
        DrawResults[i].ID = RandRange(first, last);
        DrawResults[i].Number = i+1;

        for (int j=0; j<i; j++)
        {
            if (DrawResults[i].ID == DrawResults[j].ID)
            {
                i = i-1;
                break;
            }
        }

    }
}

void PrintDrawnNumbers()
{
    printf("Wylosowano nastepujące liczby: \n");
    printf("ID  | Numer liczby \n");
    printf("--------------------\n");

        for (int i=0; i<*wskRozmiar; i++)
    {
        printf("%3d | %3d\n", DrawResults[i].Number, DrawResults[i].ID);
    }
}

int main()
{
    srand(time(NULL));
    DrawNumbers(1,49, *wskRozmiar);
    PrintDrawnNumbers();

    return 0;
}
0

Niepotrzebny realloc, wystarczyłby malloc
i zmienne globalne, a fuj!

0

Może spójrz na pewne sensowne rozwiązanie:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
typedef struct {
    unsigned *tb;
    unsigned size;
} DrawResults;
 
unsigned RandRange(unsigned min,unsigned max)
  {
   return min+rand()%(max-min+1);
  }
  
void swap(unsigned *a,unsigned *b)
  {
   unsigned tmp;
   tmp=*a;
   *a=*b;
   *b=tmp;
  }

int DrawNumbers(unsigned first,unsigned last,unsigned size,DrawResults *dr)
  {
   unsigned i,r,tmp,bigsize,*tb;
   bigsize=(last-first+1);
   if(bigsize<size) return 0;
   tb=malloc(bigsize*sizeof(unsigned));
   for(i=0;i<bigsize;++i) tb[i]=first+i;
   for(i=0;i<size;++i) swap(tb+i,tb+i+rand()%(bigsize-i));
   dr->size=size;
   dr->tb=realloc(tb,size*sizeof(unsigned));
   return 1;
  }

void PrintDrawnNumbers(DrawResults *dr)
  {
   unsigned i;
   printf("Wylosowano nastepujące liczby:\n");
   printf("ID  | Numer liczby\n");
   printf("--------------------\n");
   for(i=0;i<dr->size;++i) printf("%3d | %3d\n",dr->tb[i],i+1);
  }
 
int main()
  {
   DrawResults dr={NULL,0};
   srand(time(NULL));
   DrawNumbers(1,49,10,&dr);
   PrintDrawnNumbers(&dr); 
   return 0;
  }
0

@_13th_Dragon Mam nadzieję, że nie piszesz nic krytycznego?

 tb=malloc(bigsize*sizeof(unsigned));
   for(i=0;i<bigsize;++i) tb[i]=first+i;
   for(i=0;i<size;++i) swap(tb+i,tb+i+rand()%(size-i));
   dr->size=size;
   dr->tb=realloc(tb,size*sizeof(unsigned));

Po co taka zabawa? Alokowanie bgsiza, by zaraz go zwolnić i alokować tyle ile trzeba?
Nie widzę zwolnienia pamięci, która jest przydzielona.

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