LINGUAGEM: Linguagem C - Capítulo 3 - Parte 2


typedef, ponteiros para funções e union


Exemplo

#ifndef MENU_H
#define MENU_H

typedef struct item {
 char * str;
 void(* fun)(void);
 struct item * sub;
 struct item * sup;
 struct item * nxt;
 struct item * prv;
} Item;

void addMenuItem (const char * str, void(* fun)(void));
void addMenuSubItem (const char * str_i,const char * str_si, void(* fun)(void));
void loopMenu(void);

#endif

/** menu.c */

#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include "buffer.h"
#include "menu.h"

Item * menu;
Item * menu_sel;
int sub_items_visible;

...



Exemplo

/** menu.c */

...

void addMenuItem (const char * str, void(* fun)(void)) {  /** PARAM PONT. FUNCAO */
 Item * ptr;
 
 if ( menu == NULL ) {
  menu = (Item *) malloc(sizeof (Item));
     ptr = menu;
      ptr->prv = NULL;
    } else {
        ptr = menu;
         while ( ptr->nxt ) {
           if ( strcmp(ptr->str,str) == 0 )
           return;
           ptr = ptr->nxt;
           }
           ptr->nxt = (Item *) malloc(sizeof (Item));
           ptr->nxt->prv = ptr;
     ptr = ptr->nxt;
 }
 ptr->str = strdup(str);
 ptr->fun = fun;           /** ATRIBUICAO PONTEIRO FUNCAO **/
 ptr->sub = NULL;
 ptr->sup = NULL;
 ptr->nxt = NULL;
}


...
{
  ...
              case ENTER: 
                    if ( menu_sel->fun )
                       (*(menu_sel->fun))();   /** CHAMADA FUNCAO VIA PONTEIRO **/
                    else
   ...
}



#define ENTER  13
#define ESC    27
#define RTARR  77
#define LTARR  75
#define UPARR  72
#define DWARR  80

union  u_type{
      int i;
      char ch;
} ich;


void loopMenu() {

 while ( 1 ) {
  
        ich.i = getch();
  switch ( ich.ch ) {
               case ENTER: 
 ....

CÓDIGO COMPLETO

O código abaixo implementa um sistema de menus para um programa de controle acadêmico.

/** main.c */
#include <stdio.h>
#include <stdlib.h>

#include "menu.h"


void f() {
     printf("function activation!");
     getch();
}

extern Item * menu;
extern Item * menu_sel;
extern int sub_items_visible;

int main(int argc, char *argv[])
{
 addMenuItem("CADASTRO",NULL);
 addMenuItem("MATRICULA",NULL);
 addMenuItem("RELATORIO",NULL);

 addMenuSubItem("CADASTRO","Alunos",f);
 addMenuSubItem("CADASTRO","Professores",f);
 addMenuSubItem("CADASTRO","Disciplinas",f);

 addMenuSubItem("MATRICULA","Matriculas",f);
 addMenuSubItem("MATRICULA","Turma",f);

    loopMenu();

    return 0;
}

#ifndef MENU_H
#define MENU_H

typedef struct item {
 char * str;
 void(* fun)(void);
 struct item * sub;
 struct item * sup;
 struct item * nxt;
 struct item * prv;
} Item;

void addMenuItem (const char * str, void(* fun)(void));
void addMenuSubItem (const char * str_i,const char * str_si, void(* fun)(void));
void loopMenu(void);

#endif

/** menu.c */

#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include "buffer.h"
#include "menu.h"

Item * menu;
Item * menu_sel;
int sub_items_visible;



void addMenuItem (const char * str, void(* fun)(void)) {
 Item * ptr;
 
 if ( menu == NULL ) {
  menu = (Item *) malloc(sizeof (Item));
     ptr = menu;
      ptr->prv = NULL;
    } else {
        ptr = menu;
         while ( ptr->nxt ) {
           if ( strcmp(ptr->str,str) == 0 )
           return;
           ptr = ptr->nxt;
           }
           ptr->nxt = (Item *) malloc(sizeof (Item));
           ptr->nxt->prv = ptr;
     ptr = ptr->nxt;
 }
 ptr->str = strdup(str);
 ptr->fun = fun;
 ptr->sub = NULL;
 ptr->sup = NULL;
 ptr->nxt = NULL;
}

void addMenuSubItem (const char * str_i,const char * str_si, void(* fun)(void)) {
 Item * ptr;
 
    ptr = menu;
    
 while ( ptr ) {
  if ( strcmp(ptr->str,str_i) == 0 )
   break;
  ptr = ptr->nxt;
 }

 if ( ptr == NULL )
  return;

 if ( ptr->sub == NULL ) {
  ptr->sub = (Item *) malloc(sizeof (Item));
  ptr->sub->prv = NULL;
  ptr->sub->sup = ptr;
  ptr = ptr->sub;
 } else {
  ptr = ptr->sub;

  while ( ptr->nxt ) {
   if ( strcmp(ptr->str,str_si) == 0 ) {
                 ptr->fun = fun;
     return;
            }
   ptr = ptr->nxt;
  }

  ptr->nxt = (Item *) malloc(sizeof (Item));
  ptr->nxt->prv = ptr;
  ptr->nxt->sup = ptr->sup;
  ptr = ptr->nxt;
 }
 ptr->str = strdup(str_si);
 ptr->fun = fun;
 ptr->sub = NULL;
 ptr->nxt = NULL;
}



void drawMenu(void) {
 Item * ptr = menu, * sel_ptr;
    int x = 1, y = 1 ,   sel_x;
    int n = strlen( ptr->str);
    
 while ( ptr ) {
          
          if ( menu_sel == ptr || menu_sel->sup == ptr ) {
             sel_ptr = ptr;
       sel_x = x;
          }
          
          
          if ( menu_sel == ptr ) {
               xyputs(x,y,">");
               xyputs(x+n+4,y,"<");
          }
          xyputs(x+2,y,ptr->str);

          x += n + 5 , ptr = ptr->nxt;
 }

    if ( sub_items_visible ) {
         int i;
         ptr = sel_ptr -> sub;
         
         for (i = 0 ; i<n; i++ )
             xyputs(sel_x+2+i,y+1,"-");
         y +=2 ;
         while ( ptr ) {
            if ( menu_sel == ptr )
                  xyputs(sel_x,y,">");
         
               xyputs(sel_x+2,y,ptr->str);
               y++ , ptr = ptr->nxt;
         }
    }
}

#define ENTER  13
#define ESC    27
#define RTARR  77
#define LTARR  75
#define UPARR  72
#define DWARR  80

union  {
      int i;
      char ch;
} ich;


void loopMenu() {
     menu_sel = menu;
 while ( 1 ) {
  clearBuf();
  drawMenu();
  displayBuf();
  
        ich.i = getch();
  switch ( ich.ch ) {
               case ENTER: 
                    if ( menu_sel->fun )
                       (*(menu_sel->fun))();
                    else
                    if ( menu_sel -> sub ) {
                       sub_items_visible = 1;
                       menu_sel = menu_sel->sub;
                    }
                    break;
               case ESC:
                     if ( menu_sel -> sup ) {
                       sub_items_visible = 0;
                       menu_sel = menu_sel->sup;
                       break;
                    } else
                      return;
              
               case UPARR:
                    if ( menu_sel->sup && menu_sel->prv )
                       menu_sel = menu_sel->prv;
                    else
                    if ( menu_sel->sup ) {
                       sub_items_visible = 0;
                       menu_sel = menu_sel->sup;
                    } 
                    else
                       sub_items_visible = 0;
                    break;
               case DWARR:
                    if ( menu_sel -> sub ) {
                       sub_items_visible = 1;
                       menu_sel = menu_sel->sub;
                    } else
                    if (  menu_sel->nxt )
                       menu_sel = menu_sel->nxt;
                    break;                       
               case LTARR:
                    if ( menu_sel->sup ) {
                         if ( menu_sel->sup->prv )
                            menu_sel = menu_sel->sup->prv;
                    } else
                    if ( menu_sel->prv ) 
                       menu_sel = menu_sel->prv;
                    break;
               case RTARR:
                    if ( menu_sel->sup ) {
                         if ( menu_sel->sup->nxt )
                            menu_sel = menu_sel->sup->nxt;
                    } else
                    if (  menu_sel->nxt )
                       menu_sel = menu_sel->nxt;
                    break;                       
  }

 }

}

/** buffer.h */

#ifndef BUFFER_H
#define BUFFER_H

void clearBuf(void);
void xyputs(unsigned short x, unsigned short y, const char * str);
void displayBuf(void);


#endif
/** buffer.c */

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

#define BUFW 80
#define BUFH 24

char buf[BUFH][BUFW];

void clearBuf(void){
 int x,y;

 for( y = 0; y < BUFH; y++ ) {
  for( x = 0; x < BUFW; x++ )
   buf[y][x] = ' ';
 }
}

void xyputs(unsigned short x, unsigned short y, const char * str) {

 x %= BUFW;
 y %= BUFH;

 for ( ; *str ; str++ ) {
  switch( *str ) {
   case '\n' : x = 0, y = (y + 1) % BUFH;
    break;
   case '\b' :
    if ( x == 0 ) {
     x = BUFW - 1;
     y = y == 0 ? BUFH - 1 : y -1;
    } else
     x --;
    break;
   default :
    buf[y][x] = *str;
    x = (x+1)%BUFW;
    y = x == 0 ? (y+1)%BUFH : y;

  }
 }
}

void displayBuf(void) {
     //fseek(stdout,sizeof buf,SEEK_END);
     system("cls");
     fwrite(&buf,sizeof buf ,1,stdout);
}

Bibliografia e fonte:

  • [CCT] Schildt, H. (1996) C, completo e total: 3a Ed.. São Paulo, Makron.
  • LP, UFMA; Coutinho, Lucian. Linguagem de programação para ciencia da computação da ufma.http://www.deinf.ufma.br/~lrc/2009.1/LP/
  • [K&R] KERNIGHAN, B. e RITCHIE, D. (1990) C, a linguagem de programação: padrão ANSI. Rio de Janeiro: Campus.
  • DEITEL, H. M. (1999) Como programar em C. Rio de Janeiro: LTC.
  • Módulo Consultoria e Informática (1989) Linguagem C: programação e aplicações. Rio de Janeiro: LTC.