fredericopissarra Posted May 25, 2019 at 01:50 PM Share Posted May 25, 2019 at 01:50 PM A turma da OOP acredita que lidar com coisas como polimorfismo é impossível em linguagens "estruturadas". Eis um exemplo de como fazer uma lista de encadeamento simples, em C, com elementos de diversos "tipos"... Considere a palavra-reservada struct: Ela existe para juntar vários tipos em um único container e de forma ordenada. Assim, se definirmos um nó genérico como: typedef struct node_s { struct node_s *next; } node_T; // _T porque _t não deve ser usado! Podemos definir uma estrutura de controle para uma lista como: // Usado para inicializar uma estrutura de lista vazia. #define EMPTY_LIST { NULL, NULL } typedef struct list_s { node_T *head, *tail; } list_T; Podemos agora usar a regra de que todo elemento que será colocado nessa lista deve definir, primeiro, um ponteiro do tipo node_T que aponte para o próximo item da lista... Por exemplo, suponha que eu queira criar uma lista de vetores 3D (x,y,z). Posso definir os elementos como: struct vec3d_element_s { node_T *next; // isso TEM que estar aqui! // nosso vetor: double x, y, z; }; Eis uma rotina que adiciona elementos no início de uma lista: // note que elemp é ponteiro para void, aceita qualquer ponteiro! void addhead( list_T *lstp, void *elemp ) { node_T *p = elemp; p->next = lstp->head; lstp->head = p; // o elemento é a nova 'cabeça' da lista. // Se a lista estiver previamente vazia, temos um novo 'rabo'. if ( ! lstp->tail ) lstp->tail = p; } Note que, junto com a definição da estrutura de lista, defini um macro EMPTY_LIST. Isso permite o seguinte uso: // define uma lista vazia. list_T list = EMPTY_LIST; struct vec3d_element_s *elemp; // ponteiro para nosso novo elemento. elemp = malloc( sizeof *elemp ); // aloca elemento. elemp->x = 0.0; // inicializa dados do elemento. elemp->y = 1.0; elemp->z = sqrt(2.0); // adiciona elemento na lista: addhead( &list, elemp ); Note que nossa lista aceita QUALQUER estrutura que tenha, como seu primeiro membro, um ponteiro para node_T nomeado de next. Poderíamos fazer algo assim: enum vec_type { V2D, V3D, V4D }; struct vec_element_s { node_T *next; enum vec_type vtype; double v[0]; // yep... tamanho 0! }; ... list_T list = EMPTY_LIST; ... // Aloca vetor 2D, inicializa-o e coloca na lista: struct vec_element_s *v2d; v2d = malloc( sizeof *v2d + 2*sizeof( double ) ); v2d->vtype = V2D; v2d->v[0] = 1.0; v2d->v[1] = 2.0; addhead( &list, v2d ); // Aloca vetor 3D, inicializa-o e coloca na lista. struct vec_element_s *v3d; v3d = malloc( sizeof *v3d + 3*sizeof( double ) ); v3d->vtype = V3D; v3d->v[0] = 1.0; v3d->v[1] = 2.0; v3d->v[1] = 3.0; addhead( &list, v2d ); // percorre a lista e faz algo com os elementos: node_T *p; p = list.head; while ( p ) { doSomething( p ); p = p->next; } Na hora de percorrer a lista podemos usar o membro vtype para dedicir o tamanho do array v. Mas, note que a lista não se importa com o tipo do elemento, desde que ele tenha o ponteiro next como primeiro item. Link to comment Share on other sites More sharing options...
fredericopissarra Posted May 25, 2019 at 01:58 PM Author Share Posted May 25, 2019 at 01:58 PM PS; É claro... se quiser adicionar elementos no final da lista: void addtail( list_T *lstp, void *elemp ) { node_T *p = elemp; // esse será o último elemento! p->next = NULL; if ( ! lstp->tail ) // lista vazia? { lstp->head = lstp->tail = p; return; } // ajusta o nó tail atual para o novo nó. lstp->tail->next = p; lstp->tail = p; } Link to comment Share on other sites More sharing options...
growlnx Posted May 27, 2019 at 12:35 AM Share Posted May 27, 2019 at 12:35 AM Olá, Gostaria de aproveitar o tópico e compartilhar este livro do Dr. Axel T. Schreiner que encontrei pesquisando sobre o assunto. Ele aborda o uso da orientação a objetos na linguagem C. Objekt-orientierte Programmierung mit ANSI-C Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.