Jump to content

Recommended Posts

Posted

Bom dia,

A primeira coisa que se me ocorre ao olhar para isso, é uma "maquina de estados".

Creio que resolve o problema dos menus de forma simples.

Cordiais cumprimentos,

Apocsantos

"A paciência é uma das coisas que se aprendeu na era do 48k" O respeito é como a escrita de código, uma vez perdido, dificilmente se retoma o habito"

Posted

Boa tarde,

Vou deixar um exemplo, apenas por "brincadeira", mas não despensa que estudes.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//carrega os headers readline e history, que fazem parte das biblitecas GNU Readline Library e se enconram na pasta readline
//devem ser previamente instalados, no caso, usando GNU/Linux Ubunto, com o seguinte comando:
// sudo apt-get install libreadline-dev
#include <readline/readline.h>
#include <readline/history.h>
#include "main.h"
// cria uma estrutura com o nome Estado, contendo o local em que o user se encontra.
typedef enum {
 MAIN // principal
,CONT // conteudo
,ESCA // Opcao
,SAIR
} estado;

//Estrutura Comando, declara variável tipo estado, e apontadores do tipo caracter e função.
typedef struct {
estado es;
char *cmd;
void (*f)(char **,int);
char *args;
char *descricao;
} comando;
void dummy(char **,int); //função dummy recebe como argumentos um duplo apontador de caracteres, e um apontador de inteiro
// função do tipo comando contendo os descritivos e chamando as funções respetivas a cada designação de comando.
comando cmds[] = {
 {MAIN,"conteudo", troca_estado,  "","Gerir conteudo"}
,{CONT,"adicionar", conteudo_adicionar, "","Cria um conteudo e adiciona na lista de conteudos"}
,{CONT,"listar", conteudo_listar, "","Mostra todos os conteudos disponiveis"}
,{CONT,"remover", conteudo_remover, "id","Remove permanentemente um determinado conteudo "
 "da lista de conteudos"}
,{CONT,"alterar", conteudo_alterar, "","Cria um conteudo e substitui um existente"}
,{CONT,"carregar", conteudo_carregar, "filename", "Carrega um conteudo de um ficheiro"}
,{CONT,"salvar", conteudo_salvar, "id filename", "Salva um conteudo para um ficheiro, se o ficheiro ja existir reescreve."}
,{CONT,"ajuda",  imprime_ajuda,  "","Mostra informacoes de ajuda para os comandos "
 "possiveis num determidado estado do programa"}
,{CONT,"sair",  troca_estado,  "","Volta ao menu principal"}
,{MAIN,"escalonamento", troca_estado, "","Gerir escalonamento"}
,{ESCA,"ajuda",  imprime_ajuda,  "","Mostra informacoes de ajuda para os comandos "
 "possiveis num determidado estado do programa"}
,{ESCA,"listar", esca_listar,  "","Lista a programacao"}
,{ESCA,"l_utilizados",esca_l_utilizados,"","Lista os conteudos utilizados na programacao"}
,{ESCA,"sair",   troca_estado, "","Volta ao menu principal"}
,{MAIN,"ajuda",  imprime_ajuda,  "","Mostra informacoes de ajuda para os comandos "
 "possiveis num determidado estado do programa"}
,{MAIN,"sair",  troca_estado,  "","Sair da aplicacao"}
};
int nr_cmds;
estado _es = MAIN;
// Função SplashScreen , mostra etiqueta do trabalho
void splashScreen() {
printf("\x1b[32m");
printf("\x1b[1;5m");
printf("\x1b[0m");
}
//funca dummy a er usada na maquina de estados do menu
void dummy(char **words,int n) {
int i;
printf("Eu queria executar isto:\n");
for(i=0; i<n; i++)
 printf("%d/%d:%s\n",i,n,words[i]);
}
//funcao troca_estado, usada na maquina de estados, na transição entre estados, usados no menu
void troca_estado(char **words, int n) {
static short int ajuda_impressa[] = { 0,0}; //CONT,ESCA
if(n>1) {
 printf("ERRO: Demasiados argumentos para comando %s.\n",words[0]);
 return;
}
switch (_es) {
 case MAIN:
  if(strcmp(words[0],"conteudo")==0) {
   _es = CONT;
   if(ajuda_impressa[0]==0) {
 imprime_ajuda(NULL,0);
 ajuda_impressa[0]=1;
   }
  } else if(strcmp(words[0],"escalonamento")==0) {
   _es = ESCA;
   if(ajuda_impressa[1]==0) {
 imprime_ajuda(NULL,0);
 ajuda_impressa[1]=1;
   }
  } else if(strcmp(words[0],"sair")==0)
   _es = SAIR;
  else
   printf("ERRO: Argumento inesperado ao trocar estado.\n");
  break;
 case CONT:
 case ESCA:
  if(strcmp(words[0],"sair")==0)
   _es=MAIN;
  else
   printf("ERRO: Argumento inesperado ao trocar estado.\n");
  break;
 case SAIR:
  printf("ERRO: Argumento inesperado ao trocar estado.\n");
}
}
//funcao imprime_ajuda, usada no menu, para exibir instruções de utilização
void imprime_ajuda(char **words, int n) {
int j;
char buffer[1024];
if(n>1) {
 printf("Argumento(s) inesperado(s): %s.\n",words[1]);
}
printf("\x1b[33;1mComandos possiveis:\x1b[0m\n");
for(j=0; j<nr_cmds; j++) {
 if(_es == cmds[j].es) {
  sprintf(buffer,"%s %s",cmds[j].cmd,cmds[j].args);
  printf("\t\x1b[33m%-20s\x1b[0m: %s\n",buffer,cmds[j].descricao);
 }
}
}
//funcao strip_line, usada para dividir linhas, quando o tamanho é excedido
void strip_line(char *line, char **words, int *n) {
char *ptr;
char delim[] = " \t\r";
int i=0;
ptr = strtok(line,delim);
while(ptr!=NULL) {
//  words[i] = (char *)malloc( (strlen(ptr)+1)*sizeof(char));
//  strcpy(words[i],ptr);
 words[i] = strdup(ptr);
 i++;
 ptr=strtok(NULL,delim);
}
*n=i;
}
//funcao strEstado, recebe como argumentos um estado
char *strEstado(estado s) {
static char *ss[] = {
  ""
 ," [conteudo]"
 ," [escalonamento]"
};
switch(s) {
 case MAIN:
 case SAIR:
  return ss[0];
 case CONT:
  return ss[1];
 case ESCA:
  return ss[2];
}
return ss[0];
}
//funcao main
int main(int argc, char *argv[]) {
char *line;
char prompt[1024];

nr_cmds = sizeof(cmds)/sizeof(cmds[0]);
splashScreen();
imprime_ajuda(NULL,0);
strcpy(prompt,"\x1b[44mGestor\x1b[0m >> ");
while((line = readline(prompt))) {
 char *words[100];
 int n=0;
 add_history(line);
 strip_line(line,words,&n);
 int i,run=0;
 for(i=0; i<nr_cmds; i++) {
  if(_es==cmds[i].es && strcmp(cmds[i].cmd,words[0])==0) {
   cmds[i].f(words,n);
   run=1;
   break;
  }
 }
 if(run==0) {
  printf("Comando desconhecido: %s.\n",words[0]);
 }
 // free words & line
 for(i=0; i<n; i++)
  free(words[i]);
 free(line);

 // reset prompt
 sprintf(prompt,"\x1b[44mGestor%s\x1b[0m >> ",strEstado(_es));
}
return 0;
}

Este código é antigo e foi feito para um projecto académico, faz mais de 2 anos... Espero que te dê para teres umas luzes de uma das soluções.

De qualquer das formas estou de acordo com o HHH, podes fazer isto de forma bem mais simples.

Cordiais cumprimentos,

Apocsantos

"A paciência é uma das coisas que se aprendeu na era do 48k" O respeito é como a escrita de código, uma vez perdido, dificilmente se retoma o habito"

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.