Skocz do zawartości

Ultimate Queue


Sanczo

Rekomendowane odpowiedzi

Witajcie! Chce stworzyć kolejkę w C, ale żeby była uniwersalna dla dowolnego typu danych jakie chce w niej przechowywać, tzn. raz mam ochotę przechować w niej węzeł taki:

 

struct node
{
int pid;
int ppid;
char *name;
char *cmdline;
struct node* next;
};

a raz taki:

struct node
{
char *user;
char *group;
struct node* next;
};

dla

struct lista
{
int size;
struct node *top;
struct node *tail;
};

 

Dodatkowo chce obie możliwości wykorzystać w jednym programie. Ogólnie chodzi o mniej złożoną implementację tego co jest w glibc czyli gqueue, na własną potrzebę.

Jakieś sugestie?

Odnośnik do komentarza
Udostępnij na innych stronach

Moze tak:

 

struct data1
{
int pid;
int ppid;
char *name;
char *cmdline;
};

struct data2
{
char *user;
char *group;
};

i teraz

struct node {
struct data1* d1;
struct data2* d2;
struct node* next;
}

dla

struct lista
{
int size;
struct node *top;
struct node *tail;
};

 

i jesli chcesz przechowywac pierwszy typ danych, to robisz

xxx.d1 = new data1();

xxx.d2 = NULL;

 

a jesli chcesz przechowywac drugi typ danych, to roibisz na odwrot:

xxx.d1 = NULL;

xxx.d2 = new data2();

 

Odnośnik do komentarza
Udostępnij na innych stronach

struct node {
struct data1* d1;
struct data2* d2;
struct node* next;
}

 

można prościej:

 

typedef struct node {
void *dane;
struct node* next;
} NODE;

 

Z igły zrobiłem widły, problem nie był złożony smile.gif

Ale dziękuje za pomoc i pozdrawiam

Odnośnik do komentarza
Udostępnij na innych stronach

typedef struct node {
void *dane;
struct node* next;
} NODE;

 

W powyzszym przykladzie mozesz oczywiscie do pola dane przypisac zarowno

wskaznik na pierwsza jak i na druga strukture, ale nie przechowujesz nigdzie

informacji o tym jaki faktycznie wskaznik zostal utworzony. Dlatego w tym przypadku

trzeba by jeszcze dodac dodatkowe pole typu, np. int typ; przyjmujacy wartosci:

0 - mamy wskaznik na pierwsza strukture, 1 - mamy wskaznik na druga strukture.

 

Pozdrawiam,

Marcin Załęczny

Odnośnik do komentarza
Udostępnij na innych stronach

m_zaleczny Pole dane jest wskaźnikiem do każdego typu danych, jednak jego przeznaczeniem jest wskazywanie na strukturę z danymi obecnego węzła. Natomiast next wskazuje na kolejny wezeł, wygląda to ok dla mnie i działa wyśmienicie.

Dodawanie kolejnej zmiennej dla typu wydaje mi się zbedne, nie do końca rozumiem jego przeznaczenie bo całość jest czytelna smile.gif

 

pozdrawiam

Odnośnik do komentarza
Udostępnij na innych stronach

przyjmujacy wartosci:

0 - mamy wskaznik na pierwsza strukture, 1 - mamy wskaznik na druga strukture.

Chodzilo o to ze musisz sobie w strukturze dodac jeszcze jedna zmienna (flage) okreslajaca na jaki typ struktury wskazuje wskaznik czy na pierwszy czy na drugi. Ale tutaj mozna sie bez tego obejsc mozna by np. sprawdzac rozmiar wskazywanej struktury(sizeof) przez co okreslic na jaka wskazujemy...

 

Odnośnik do komentarza
Udostępnij na innych stronach

Tak jak pisze !Ci chodzilo mi wlasnie o taka dodatkowa flage pozwalajaca rozpoznac na jaka strukture faktycznie wskazuje wskaznik wink.gif Otoz dla uproszczenia wyobrazmy sobie ponizsza tablice:

stuct dane1;
struct dane2;
void *tab[4];
dane1 *d1;
dane2 *d2;

tab[0] = (void*)new dane1();
tab[1] = (void*)new dane2();
tab[2] = (void*)new dane1();
tab[3] = (void*)new dane2();

 

i teraz gdzies w kodzie chcemy przetworzyc wszystkie elementy tej tablicy:

 

for (int i = 0; i < 4; i++) {
   // jesli nie mamy flagi okreslajacej typ danej w elemencie tab[i], to mamy problem...
   // tab[i] zawiera wskaznik nieokreslonego typu (void*) i nie wiemy czy rzutowac
   // na dane1 czy na dane2
}// for

 

Nie wiem czy funkcja sizeof by pomogla, bo dla kazdego i sizeof zwroci 4:

sizeof(tab) = 4, natomiast sizeof(*tab) powinno spowodowac bledy kompilacji.

Ale moze sie myle a nie moge teraz tego sprawdzic.

 

Odnośnik do komentarza
Udostępnij na innych stronach

Nie wiem czy funkcja sizeof by pomogla, bo dla kazdego i sizeof zwroci 4:

sizeof(tab) = 4, natomiast sizeof(*tab) powinno spowodowac bledy kompilacji.

Hmmm nie jestem pewien czy wyrzuci bledy mysle ze nie powinien ale mozna to sprawdzic. To podalem czysto teoretycznie. Tylko juz dzisiaj tego nie zrobie czas nie pozwala... tongue.gif

Odnośnik do komentarza
Udostępnij na innych stronach

Dzięki ale taka zmienna/wskaźnik jest nie potrzebna. Sam nie mam kłopotów w połapaniu się w tym na jakim typie operuje w danej chwili, a jeśli ktoś będzie chciał zajżeć w kod, będą dla niego przygotowane komentarze oraz mam nadzieje wyczerpująca dokumentacja smile.gif

 

pozdrawiam

Odnośnik do komentarza
Udostępnij na innych stronach

Dzięki ale taka zmienna/wskaźnik jest nie potrzebna. Sam nie mam kłopotów w połapaniu się w tym na jakim typie operuje w danej chwili,

Tzn. jak to rozwiazales, bo chyba nie starasz sie zapamietac ktora nazwa zmiennej odpowiada danej strukturze. Jak w programie rozrozniasz te dwa typy danych??

Odnośnik do komentarza
Udostępnij na innych stronach

!Ci Ok, po kolei: (pisze z głowy)

 

1. Potrzebuje 2 kolejki:

- na użytkowników

- na procesy

 

int main()
{
LISTA *list_p=(LISTA*)malloc(sizeof(LISTA));  // dla procesów
LISTA *list_u=(LISTA*)malloc(sizeof(LISTA));  // dla user'ów

. . .
}

 

2. Gdy do którejś listy chce dodać odpowiedni węzeł:

mam funkcje:

//ogólna
void dodaj(LISTA *list,void *(*add)(void))
{
NODE *n=(NODE*)malloc(sizeof(NODE));
n->data=add();

n->next=NULL;

if(list->head==NULL)
       list->head=n;

if(list->tail!=NULL)
 list->tail->next=n;

list->tail=n;
list->size++;
}



//dla N_USER
N_USER* dodaj_u(void)
{
N_USER *n=(N_USER*)malloc(sizeof(N_USER));

n->user_name=NULL;
n->term_type=NULL;
n->type_log=0;

return n;
}


//dla N_PROC
N_PROC* dodaj_p(void)
{
N_PROC *n=(N_PROC*)malloc(sizeof(N_PROC));

n->pid=0;
n->ppid=0;
n->cmdline=NULL;
n->name=NULL;
n->uid=0;
n->gid=0;
n->state=NULL;
n->dfn=0;

return n;
}

 

Kolejka ta ma zastosowanie tylko w tym programie (takie jest założenie) więc dobrze by nie zawierała niepotrzebnych składowych smile.gif

Odnośnik do komentarza
Udostępnij na innych stronach

Ok ok... Rozumiem tylko ja caly czas zakladalem ze uzywasz tylko jednej kolejki do ktorej wrzucasz zarowno jeden jak i drugi typ struktury tongue.gif . Dlatego pisalem o dodatkowej fladze wtedy byloby takie rozwiazanie lub podobne potrzebne, aby podczas wykonywania jakis dzialan na elementach kolejki wiedziec jaki typ aktualnie "obrabiamy"....

Odnośnik do komentarza
Udostępnij na innych stronach

Właśnie sprawdziłem działanie sizeof. Otóż tak jak pisałem wcześniej kompilator

nie przepuści instrukcji sizeof(*v), gdzie v jest typu void*. A oto przykladowy kod

demonstrujący:

#include <iostream>
using namespace std;

struct dane1 {
int id;
string nazwa;
};

struct dane2 {
int id;
string nazwa;
float dl;
};

int main()
{
void *v1 = new dane1;
void *v2 = new dane2;
dane1 *d1 = new dane1;
dane2 *d2 = new dane2;

cout << "sizeof(dane1): " << sizeof(dane1) << endl;
cout << "sizeof(dane2): " << sizeof(dane2) << endl;
cout << "sizeof(v1): " << sizeof(v1) << endl;
cout << "sizeof(v2): " << sizeof(v2) << endl;
cout << "sizeof(d1): " << sizeof(d1) << endl;
cout << "sizeof(d2): " << sizeof(d2) << endl;
cout << "sizeof(*v1): " << sizeof(*(dane1*)v1) << endl;
cout << "sizeof(*v2): " << sizeof(*(dane2*)v2) << endl;
cout << "sizeof(*d1): " << sizeof(*d1) << endl;
cout << "sizeof(*d2): " << sizeof(*d2) << endl;

delete (dane1*)v1;
delete (dane1*)v2;
delete d1;
delete d2;

return 0;
}

po zamianie linijek

cout << "sizeof(*v1): " << sizeof(*(dane1*)v1) << endl;
cout << "sizeof(*v2): " << sizeof(*(dane2*)v2) << endl;

na

cout << "sizeof(*v1): " << sizeof(*v1) << endl;
cout << "sizeof(*v2): " << sizeof(*v2) << endl;

dostaniemy błędy kompilacji. Zatem sizeof nie przyda nam się do rozpoznawania

typu wskazywanego obiektu.

Odnośnik do komentarza
Udostępnij na innych stronach

m_zaleczny

 

sizeof(*v), gdzie v jest typu void*

 

Czy przypadkiem nie sprawdzasz tutaj rozmiaru adresu question.gifsmile.gif

 

Bez rzutowania się nie obejdzie, na każdym kroku musisz dawać rzutowanie na odpowiedni typ np. (dane1*)->id...

 

!Ci Chyba dodanie zmiennej to najlepsze co można zrobić...

Odnośnik do komentarza
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się
×
×
  • Dodaj nową pozycję...