Mudanças entre as edições de "AULA Proposta de Projetos - Programação 1 - Engenharia"

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar
Linha 352: Linha 352:
  
  
==Exemplo de REGISTRO COM "LACUNAS LIVRES"==
+
==Exercício sobre Gerenciamento de REGISTRO (structs) COM "LACUNAS LIVRES"==
 +
 
 +
Reimplementar o programa abaixo, modificando as funções adicionar_usuario e remover_usuario() para que usem a função
 +
retornar_ptr_item_livre_tab_usuarios() no lugar de retornar_item_livre_tab_usuarios().
  
 
<syntaxhighlight lang=c>
 
<syntaxhighlight lang=c>
Linha 364: Linha 367:
 
/******************************************/
 
/******************************************/
 
/*
 
/*
Para fins didáticos, demonstramos como gerenciar um
+
*Para fins didáticos, demonstramos como gerenciar um
 
vetor de structs marcando registros livres através de um flag
 
vetor de structs marcando registros livres através de um flag
 +
* Note que existem formas mais eficientes de fazer busca em tabelas (ver PRG 2)
 
*/
 
*/
 
/******************************************/
 
/******************************************/
Linha 393: Linha 397:
  
 
struct tipo_usuario{
 
struct tipo_usuario{
  char nome[TAM_NOME];
+
    char nome[TAM_NOME];
  int idade;
+
    int idade;
  char flag;    /* se 0 registro livre - se 1 ocupado */
+
    char flag;    /* se 0 registro livre - se 1 ocupado */
 
} tab_usuarios[TAM_USER];
 
} tab_usuarios[TAM_USER];
  
Linha 402: Linha 406:
 
int main()
 
int main()
 
{
 
{
  iniciar_tabela(); /* liberar todos os registros */
+
    iniciar_tabela(); /* liberar todos os registros */
  gerenciar_usuarios();
+
    gerenciar_usuarios();
 
}
 
}
  
Linha 415: Linha 419:
  
 
     for (i=0;i<TAM_USER;i++){
 
     for (i=0;i<TAM_USER;i++){
      tab_usuarios[i].flag=LIVRE;
+
        tab_usuarios[i].flag=LIVRE;
 
     }
 
     }
 
}
 
}
Linha 425: Linha 429:
 
int retornar_item_livre_tab_usuarios()
 
int retornar_item_livre_tab_usuarios()
 
{
 
{
   int i=0;
+
    int i=0;
 +
 
 +
    while(i<TAM_USER && tab_usuarios[i].flag==OCUPADO) {
 +
        i++;
 +
    }
 +
    if (i==TAM_USER)
 +
        i=-1;
 +
    return i;
 +
}
 +
 
 +
/*
 +
  retorna -1 se não existe item livre na tabela
 +
   ou retorna o índice onde existe item livre
 +
*/
 +
struct  tipo_usuario *retornar_ptr_item_livre_tab_usuarios()
 +
{
 +
    int i=0;
 +
    struct tipo_usuario *p =  &tab_usuarios[i];
  
  while(i<TAM_USER && tab_usuarios[i].flag==OCUPADO) {
+
    while(i<TAM_USER && p->flag==OCUPADO) {
    i++;
+
        i++;
  }
+
    }
  if (i==TAM_USER)
+
    if (i==TAM_USER)
    i=-1;
+
        p = NULL;
  return i;
+
    return p;
 
}
 
}
  
Linha 441: Linha 462:
 
void adicionar_usuario()
 
void adicionar_usuario()
 
{
 
{
  int ret;
+
    int ret;
  ret = retornar_item_livre_tab_usuarios();
+
    ret = retornar_item_livre_tab_usuarios();
  if (ret==-1)
+
    if (ret==-1)
      printf("Não existe espaço\n");
+
        printf("Não existe espaço\n");
  else {
+
    else {
      printf("Entre com usuario\n");
+
        printf("Entre com usuario\n");
      scanf("%s", tab_usuarios[ret].nome);
+
        scanf("%s", tab_usuarios[ret].nome);
      tab_usuarios[ret].flag = OCUPADO;
+
        tab_usuarios[ret].flag = OCUPADO;
  }
+
    }
 
}
 
}
  
Linha 479: Linha 500:
 
void gerenciar_usuarios()
 
void gerenciar_usuarios()
 
{
 
{
  int opcao;
+
    int opcao;
  
  do {
+
    do {
      system("clear");
+
        system("clear");
      printf("**********************************\n");
+
        printf("**********************************\n");
      printf("Menu Nível 2 - Gerenciar Usuários\n\n");
+
        printf("Menu Nível 2 - Gerenciar Usuários\n\n");
      printf("1. Adicionar Usuário\n");
+
        printf("1. Adicionar Usuário\n");
      printf("2. Remover Usuário\n");
+
        printf("2. Remover Usuário\n");
      printf("3. Sair do Gerenciar Usuários\n");
+
        printf("3. Sair do Gerenciar Usuários\n");
      printf("**********************************\n");
+
        printf("**********************************\n");
      scanf("%d",&opcao);
+
        scanf("%d",&opcao);
      switch (opcao) {
+
        switch (opcao) {
      case 1: adicionar_usuario();
+
            case 1: adicionar_usuario();
              break;
+
                break;
      case 2: remover_usuario();
+
            case 2: remover_usuario();
              break;
+
                break;
      case 3: printf("Finalizando Gerenciar Usuários...\n");
+
            case 3: printf("Finalizando Gerenciar Usuários...\n");
              sleep(1); /* tempo somente para fins de visualização */
+
                sleep(1); /* tempo somente para fins de visualização */
              break;
+
                break;
      default: printf("Opção inexistente. Tente novamente...\n");
+
            default: printf("Opção inexistente. Tente novamente...\n");
              sleep(1); /* tempo somente para fins de visualização */
+
                sleep(1); /* tempo somente para fins de visualização */
              break;
+
                break;
      }
+
        }
  
  } while (opcao != 3);
+
    } while (opcao != 3);
 
}
 
}
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  

Edição das 14h53min de 14 de setembro de 2020

Projeto final

O aluno deve propor ao professor um projeto de sua preferência que respeite os requisitos mínimos. Sendo aceito deverá desenvolver o projeto e apresentá-lo.

EM DUPLAS - de forma remota

Previsão de Execução

  • Prever execução do projeto para 5 semanas.

Requisitos mínimos

  • Utilizar funções (ao menos três além do main, sendo que devem receber argumentos e possuir retorno) e múltiplos arquivos;
  • Apresentar menu utilizando switch case;
  • Utilizar arrays, structs e Ponteiros;
  • Utilizar bibliotecas (manipulação de strings, tempo, matemática);
  • Utilizar diretivas de pré-compilação (define, compilação condicional);
  • Utilizar comentários (mas sem excesso - usar nomes significativos de funções e variáveis);
  • Não usar gotos;
  • Realizar acesso a arquivo, lendo e escrevendo informações (busque requisitos que requerem persistência de dados);

Metodologia e Entregas

No SIGAA serão criadas tarefas relativas a cada etapa.

Etapa 1

Apresentar a proposta de projeto ao professor. Construir um pequeno documento com o escopo do projeto contendo:

  1. Título do Projeto
  2. Integrantes da Equipe
  3. Breve descrição do que o programa vai FAZER (3 parágrafos)
  4. Tabela de Requisitos, Regras e Restrições: Apresentar uma tabela da forma:
    ITEM DESCRIÇÃO Comentário
    R1 Para ter acesso ao jogo batalha naval o usuário deve logar no sistema, fornecendo
    userID e senha
    R2 Para encerrar a sessão de jogo o usuário deve solicitar ENCERRAR sessão. O programa ficará esperando
    nova sessão
    R3 O jogo será realizado sobre um tabuleiro de 10x10 células onde estarão dispostos um número configurável de porta-aviôes, submarinos e
    fragatas.
    R4 O número de cada tipo de navio e o valor pode ser configurado pelo administrador do sistema.
    R5 O jogo é basicamente uma sequência de tiros onde o usuário fornece linha e coluna da célula. A célula deve ser válida. Célula válida é
    aquela onde ainda não foi
    realizado um tiro.
    : : :
  5. Lista dos ATORES do sistema Listar que vai interagir com o sistema, descrevendo-o brevemente:
    • JOGADOR: Ator que jogará contra o computador
    • ADMINISTRADOR: Ator que cadastra/descadastra usuários e configura o jogo.
  6. Descrição de Cenários de uso identificando os atores. Exemplo: em um sistema de controle de retirada de livros pode-se ter 2 atores: o aluno e o bibliotecário.
    Cenário 1: Login do Administrador/Jogador
    Cenário 2: Cadastro de jogador - Ator principal: ADMINISTRADOR
    Através de uma interface o ADMINIUSTRADOR seleciona inserção de alunos.
    Entra com o nome do jogador
    Entra coma a senha provisória
    Finaliza o registro.
    Cenário 3: Configuração do Jogo...
    Cenário 4:
  7. Proposta de cronograma: Exemplo:
    • Semana 0 (do dia XX/YY/ZZ): Documento de Especificação
    • Semana 1 (do dia XX/YY/ZZ): Projeto Simplificado e Início da Implementação (OBRIGATÓRIO)
    • Semana 2 (do dia XX/YY/ZZ): Implementação dos cenários 1 e 2
    • Semana 3 (do dia XX/YY/ZZ): Implementação dos cenários 3 e 4
    • Semana 4 (do dia XX/YY/ZZ): Testes Finais


AVALIAÇÃO DA ETAPA: Será verificado se cada ITEM previsto foi atendido.

Etapa 2 - Projeto Simplificado e Início da Implementação

  • O Projeto Simplificado deve apresentar:
  1. Uma VISÃO das principais estruturas de dados que serão utilizadas no processamento: Exemplo:
    • Uma tabela (vetor) de usuários da forma:
     
    struct tipo_aluno{ 
     char nome[TAM_NOME];
     char matricula[TAM_MAT];
    }; // colocar no .h 
    
    struct tipo_aluno TabelasAlunos[100];
    
    • Uma Matriz que representa o tabuleiro da Batalha Naval ...
    • Uma Tabela de estruturas que representam tipos de navios, valor de cada um
  2. Uma VISÃO de funções (com menus de primeiro nível, segundo nível etc) e arquivos (módulos) que compõem o sistema. Prever um arquivo main.c que contém a função main() e arquivos cabeçalhos. Apresentar os arquivos .c e .h zipados.
  3. Uma primeira implementação de protótipo (projeto no CLion) de funções (menus de nível 1, nível 2...) e de arquivos. Colocar em arquivo zip e submeter no SIGAA.

Etapa 3

  • Controle de Desenvolvimento: postar código fonte no SIGAA

Etapa 4

  • Controle de Desenvolvimento: postar código fonte no SIGAA

Etapa N

  • Defesa Individual: A definir+

Algumas ideias de projetos

  • Categoria Jogos
    • Batalha Naval com controle de usuários, configuração de navios e biblioteca ncurses.
    • Space Battle simplificado com controle de usuários. O usuário controla um laser que é disparado a partir de uma célula da última linha de uma matriz.Objetos caem randomicamente.
    • Jogo da Velha com controle de usuários.
    • Um Sistema Gerador de Apostas na MegaSena. Neste software são dadas sugestões de números para apostas de acordo com o número do sorteio da mega sena. Com este histórico armazenado é possível então entrar com um número de sorteio e digitar quais foram os números verdadeiramente sorteados na loteria federal checagem os acertos.
  • Categoria Educação
    • Palavra Cruzadas configurável.
    • Sugestão geral: veja em outras disciplinas que processos podem ser automatizados e proponha um projeto que realiza esta tarefa como de cálculos diversos de eletrônica, de rádio transmissão, etc.
    • Um Sistema de Cálculos de Eletrônica/Eletricidade. Neste software um menu apresenta várias opções de cálculo como de potencia através de tensão e corrente, como obtenção do valor de um resistor, como solução de equivalência de paralelo de vários resistores e outras. Num arquivo texto pode ser armazenado um histórico de operações realizadas.


  • Um Sistema de Codificação/Decodificação de mensagens (criptografia) usando métodos simples de Cesar e variantes.
  • Um sistema de Controle de Livros de um home office/biblioteca;
  • Categoria: Sistema de Controle de Estoque/Compras
  • Implementar controle de empréstimo de objetos. Neste software o usuário poderá digitar nomes de objetos que emprestou, a pessoa a quem emprestou e automaticamente o software guarda a data. Deve haver uma opção para gerar relatório dos itens emprestados e opção para marcar a devolução (podendo manter o registro em histórico ou apagando o registro).
  • Implementar software gerador de lista de compras. Neste software o usuário poderá digitar itens de supermercado com nome e quantidade. O software escreve num arquivo que poderá depois ser impresso. O software também pode ter função de numa segunda execução já trazer a antiga listagem digitada e permitir que o usuário apenas selecione novas quantidades ou inclua novos itens.
  • Categoria: Sistema de Controle


  • Um Sistema que controle de temperaturas das salas, monitorando em tempo real, permitindo alterações, adições e remoções das salas em tempo de execução.


Uso de Interface Gráfica (GTK)

Exemplo de Uso de Interfaces Multiníveis em modo texto

Baseado nas discussões em cboard.cprogramming.com

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

/* Autores: Professores PRG1 - IFSC -SJ   */
/******************************************/
/*
Para fins didáticos estão concentradas aqui
todas as funções para exemplificar a elaboração
de menus em modo texto.
Em versões finais o código deve ser organizado em arquivos .h
e .c, agrupando as funções conforme a funcionalidade.
Por exemplo: em um arquivo salas.c colocar as funções
de gerenciamento de sala, com os protótipos no salas.h
*/ 
/******************************************/

/******************************************/
/* Protótipos de funções  - colocar em .h */
/******************************************/

void gerenciar_usuarios();
void gerenciar_salas();
void adicionar_usuario();
void remover_usuario();
void adicionar_sala();
void remover_sala();

/******************************************/
/* Variáveis Globais                      */
/******************************************/

/* a fazer */

/******************************************/
main()
{ 
   int opcao;

   do {
      system("clear");
      printf("**********************************\n");
      printf("Menu Nível 1\n\n");
      printf("1. Gererenciar Usuários\n");
      printf("2. Gerenciar Salas\n");
      printf("3. Sair\n");
      printf("**********************************\n");
      scanf("%d",&opcao);   
      switch (opcao) {
      case 1: gerenciar_usuarios();
              break;
      case 2: gerenciar_salas();
              break;
      case 3: printf("Finalizando Programa...\n"); 
              break;
      default: printf("Opção inexistente. Tente novamente...\n");
               sleep(1); /* tempo somente para fins de visualização */
               break;
      } 
  
   } while (opcao != 3);
}

/***************************************************/
/* Esta funções deveriam estar em arquivo separado */
/***************************************************/
void gerenciar_usuarios()
{
   int opcao;

   do {
      system("clear");
      printf("**********************************\n");
      printf("Menu Nível 2 - Gerenciar Usuários\n\n");
      printf("1. Adicionar Usuário\n");
      printf("2. Remover Usuário\n");
      printf("3. Sair do Gerenciar Usuários\n");
      printf("**********************************\n");
      scanf("%d",&opcao);   
      switch (opcao) {
      case 1: adicionar_usuario();
              break;
      case 2: remover_usuario();
              break;
      case 3: printf("Finalizando Gerenciar Usuários...\n"); 
              sleep(1); /* tempo somente para fins de visualização */
              break;
      default: printf("Opção inexistente. Tente novamente...\n");
               sleep(1); /* tempo somente para fins de visualização */
               break;
      } 
  
   } while (opcao != 3);
}

void adicionar_usuario()
{
  /* aqui poderia ter um menu nível 3 */
  printf("adicionando usuário\n ");
  sleep(1);
  printf("usuário adicionado\n ");
  sleep(1);
}

void remover_usuario()
{
  /* aqui poderia ter um menu nível 3 */
  printf("removendo usuário\n ");
  sleep(1);
  printf("usuário removido\n ");
  sleep(1);
}


/***************************************************/
/* Esta funções deveriam estar em arquivo separado */
/***************************************************/

void gerenciar_salas()
{
   int opcao;

   do {
      system("clear");
      printf("**********************************\n");
      printf("Menu Nível 2 - Gerenciar Salas\n\n");
      printf("1. Adicionar Sala\n");
      printf("2. Remover Sala\n");
      printf("3. Sair do Gerenciar Salas\n");
      printf("**********************************\n");
      scanf("%d",&opcao);   
      switch (opcao) {
      case 1: adicionar_sala();
              break;
      case 2: remover_sala();
              break;
      case 3: printf("Finalizando Gerenciar Sala...\n"); 
              sleep(1); /* tempo somente para fins de visualização */
              break;
      default: printf("Opção inexistente. Tente novamente...\n");
               sleep(1); /* tempo somente para fins de visualização */
               break;
      } 
  
   } while (opcao != 3);
}

void adicionar_sala()
{
  /* aqui poderia ter um menu nível 3 */
  printf("adicionando sala\n ");
  sleep(1);
  printf("sala adicionada\n ");
  sleep(1);
}

void remover_sala()
{
  /* aqui poderia ter um menu nível 3 */
  printf("removendo sala\n ");
  sleep(1);
  printf("sala removida\n ");
  sleep(1);
}

Gerenciamento de Itens em um Vetor (array)

Um problema recorrente nos projetos é como gerenciar itens que são inseridos e colocados no vetor (array) de tamanho fixo. Em PRG 1 não estamos preocupados em propor estruturas de dados sofisticadas. Neste sentido, duas possibilidades pode se apresentar:

  • REGISTROS LIVRES SEMPRE SEM ENCONTRAM NO FINAL DA TABELA: usar um contador de itens na tabela e sempre inserir um novo item após todos os demais. Neste caso, a remoção de um item implica em deslocar todos os dados posteriores para que ocupem o espaço liberado. (ver https://www.edureka.co/blog/c-program-for-deletion-and-insertion/).
  • POSSIBILIDADE DE "LACUNAS LIVRES" NO ARRAY: usar flags indicadores de registro livre ou ocupado na tabela. A inserção de um novo item na tabela deve passar por encontrar uma posição livre, colocando o flag do registro como ocupado. A remoção implica em simplesmente colocar o flag como livre. Um contador de itens pode ser usado para facilitar a identificação caso não exista mais posições livres na tabela.


Exercício sobre Gerenciamento de REGISTRO (structs) COM "LACUNAS LIVRES"

Reimplementar o programa abaixo, modificando as funções adicionar_usuario e remover_usuario() para que usem a função retornar_ptr_item_livre_tab_usuarios() no lugar de retornar_item_livre_tab_usuarios().

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>


/* Autores: Professores PRG1 - IFSC -SJ   */
/******************************************/
/*
*Para fins didáticos, demonstramos como gerenciar um
vetor de structs marcando registros livres através de um flag
* Note que existem formas mais eficientes de fazer busca em tabelas (ver PRG 2)
*/
/******************************************/

#define LIVRE 0
#define OCUPADO 1

#define TAM_USER 10
#define TAM_NOME 20

/******************************************/
/* Protótipos de funções  - colocar em .h */
/******************************************/

void gerenciar_usuarios();
void adicionar_usuario();
void remover_usuario();
void iniciar_tabela();
int retornar_item_livre_tab_usuarios();


/******************************************/
/* Variáveis Globais                      */
/******************************************/

/* a fazer */

struct tipo_usuario{
    char nome[TAM_NOME];
    int idade;
    char flag;    /* se 0 registro livre - se 1 ocupado */
} tab_usuarios[TAM_USER];

/******************************************/

int main()
{
    iniciar_tabela(); /* liberar todos os registros */
    gerenciar_usuarios();
}

/*
  Esta função inicia a tabela com todos registros livres
  Aqui seria uma boa oportunidade para ler dados de um arquivo e iniciar a tabela
*/
void iniciar_tabela()
{
    int i;

    for (i=0;i<TAM_USER;i++){
        tab_usuarios[i].flag=LIVRE;
    }
}

/*
  retorna -1 se não existe item livre na tabela
  ou retorna o índice onde existe item livre
*/
int retornar_item_livre_tab_usuarios()
{
    int i=0;

    while(i<TAM_USER && tab_usuarios[i].flag==OCUPADO) {
        i++;
    }
    if (i==TAM_USER)
        i=-1;
    return i;
}

/*
  retorna -1 se não existe item livre na tabela
  ou retorna o índice onde existe item livre
*/
struct  tipo_usuario *retornar_ptr_item_livre_tab_usuarios()
{
    int i=0;
    struct tipo_usuario *p =  &tab_usuarios[i];

    while(i<TAM_USER && p->flag==OCUPADO) {
        i++;
    }
    if (i==TAM_USER)
        p = NULL;
    return p;
}

/*
 * Esta função insere usuário na tabela. NOTE que ela não testa se o
 * usuário já se encontra na mesma... Poderia ser criada uma função para isto...
 */
void adicionar_usuario()
{
    int ret;
    ret = retornar_item_livre_tab_usuarios();
    if (ret==-1)
        printf("Não existe espaço\n");
    else {
        printf("Entre com usuario\n");
        scanf("%s", tab_usuarios[ret].nome);
        tab_usuarios[ret].flag = OCUPADO;
    }
}

void remover_usuario()
{
    char buffer[TAM_NOME];
    int i=0;

    printf("Qual o nome do usuário a remover?\n");
    scanf ("%s", buffer);
    for (i=0;i<TAM_USER;i++){
        if (tab_usuarios[i].flag == OCUPADO && strcmp(buffer, tab_usuarios[i].nome)==0) {
            break;
        }
    }

    if (i<TAM_USER) {/* usuário encontrado */
        tab_usuarios[i].flag = LIVRE;
        printf("usuario %s removido da posição %d\n", tab_usuarios[i].nome, i);
    } else {
        printf("Usuário não se encontra na tabela\n");
    }

}

/***************************************************/
/* Esta funções deveriam estar em arquivo separado */
/***************************************************/
void gerenciar_usuarios()
{
    int opcao;

    do {
        system("clear");
        printf("**********************************\n");
        printf("Menu Nível 2 - Gerenciar Usuários\n\n");
        printf("1. Adicionar Usuário\n");
        printf("2. Remover Usuário\n");
        printf("3. Sair do Gerenciar Usuários\n");
        printf("**********************************\n");
        scanf("%d",&opcao);
        switch (opcao) {
            case 1: adicionar_usuario();
                break;
            case 2: remover_usuario();
                break;
            case 3: printf("Finalizando Gerenciar Usuários...\n");
                sleep(1); /* tempo somente para fins de visualização */
                break;
            default: printf("Opção inexistente. Tente novamente...\n");
                sleep(1); /* tempo somente para fins de visualização */
                break;
        }

    } while (opcao != 3);
}

Organização do Projeto com Múltiplos Arquivos

  • A FAZER

Olhando o exemplo acima fica claro que existem funções fortemente relacionadas ao gerenciamento de usuários: criar usuário, remover usuário, listar usuário. Para fins de organização é fortemente recomendado que estas funções sejam agrupadas em arquivo separado (um arquivo .c). Os protótipos das funções que serão vistas por outros módulos (arquivos) deverão ser colocadas em arquivos cabeçalho (.).

Supondo que existam funções relacionadas ao gerenciamento de salas, a mesma abordagem deve ser usada.

FigurasMultiplosArquivos.png

Links Interessantes