SlideShare uma empresa Scribd logo
1 de 126
Instituto Politécnico do Cávado e do Ave
Escola Superior de Tecnologia
Engenharia Eletrotécnica e de Computadores
Estruturas de dados dinâmicos em
linguagem C
Paulo Lima
Junho de 2013
ii
Resumo
Este trabalho, teve como objetivo o desenvolvimento de aplicações em
linguagem C, utilizando estruturas de dados dinâmicas.
O trabalho foi dividido em três partes, que correspondentes a diferentes
aplicações a desenvolver: gestão de um arquivo de exames de diagnóstico médico,
gestão de um simposium de medicamentos genéricos e gestão de uma prova
desportiva.
Em cada aplicação desenvolvida, foi aplicado um tipo de estrutura de dados,
sendo o objetivo utilizar listas ligadas simples, listas duplamente ligadas e finalmente
as árvores binárias de procura.
Foram analisados os problemas propostos, estruturados os dados, desenvolvidas
as funções e procedimentos de modo a criar as aplicações e no final aplicaram-se
testes ao sistema de modo a precaver possíveis erros.
Todas as aplicações foram construídas de modo a evitar situações problemáticas
para o utilizador e foram inseridos mecanismos de proteção na inserção de dados de
modo a evitar bugs e possíveis situações de conflito do sistema.
Palavras-Chave (Tema): Estruturas de dados, Listas ligadas simples, Listas
duplamente ligadas, Árvores binárias de procura.
Palavras-Chave (Tecnologias): Visual Studio, Linguagem C.
“Andar sobre as águas e fazer software a partir de uma especificação, é simples se
ambas estiverem congeladas.”
Edward V. Berard
iii
Índice
Resumo..............................................................................................................................ii
Índice ................................................................................................................................iii
Introdução ........................................................................................................................ 1
1 Linguagem C ............................................................................................................. 2
2 Estruturas de dados.................................................................................................. 3
2.1 Listas ligadas simples ......................................................................................... 3
2.2 Listas duplamente ligadas.................................................................................. 4
2.3 Árvores binárias de procura............................................................................... 5
Capítulo I........................................................................................................................... 6
1 Contexto ................................................................................................................... 7
2 Descrição Técnica ..................................................................................................... 8
2.1 Variáveis............................................................................................................. 8
2.2 Funções e procedimentos.................................................................................. 9
2.2.1 Inserir registo no início da lista ligada........................................................ 9
2.2.2 Inserir registo no fim da lista ligada ........................................................... 9
2.2.3 Introduzir dados num registo pelo utilizador........................................... 10
2.2.4 Listar registos da lista ligada..................................................................... 10
2.2.5 Gravar lista ligada em ficheiro de texto ................................................... 10
2.2.6 Carregar lista ligada do ficheiro de texto ................................................. 10
2.2.7 Pesquisar exame por paciente ................................................................. 10
2.2.8 Pesquisar exames por período de tempo ................................................ 10
2.2.9 Alterar dados de um exame ..................................................................... 11
2.2.10 Validar um código de exame .................................................................... 11
iv
2.2.11 Validar operações com a lista ligada ........................................................ 11
2.2.12 Apresentar primeira página...................................................................... 11
2.2.13 Apresentar menu...................................................................................... 11
2.2.14 Correr o menu .......................................................................................... 11
3 Desenvolvimento.................................................................................................... 12
3.1 Bibliotecas........................................................................................................ 12
3.2 Declarações...................................................................................................... 12
3.3 Métodos de inserção de dados........................................................................ 13
3.4 Restrições......................................................................................................... 14
3.5 Listar exames ................................................................................................... 15
3.6 Gravar exames ................................................................................................. 15
3.7 Carregar exames .............................................................................................. 16
3.8 Pesquisa de exames por paciente.................................................................... 16
3.9 Pesquisa de exames por data .......................................................................... 17
3.10 Alterar exames................................................................................................. 18
3.11 Validar código .................................................................................................. 19
3.12 Validar operação.............................................................................................. 20
3.13 Função main..................................................................................................... 20
4 Testes e Resultados ................................................................................................ 21
4.1 Página inicial .................................................................................................... 21
4.2 Menu................................................................................................................ 21
4.3 Listar todos os exames..................................................................................... 22
4.4 Pesquisa por paciente...................................................................................... 22
4.5 Pesquisa por data............................................................................................. 23
4.6 Inserir novo exame .......................................................................................... 23
v
5 Código fonte ........................................................................................................... 24
Capítulo II........................................................................................................................ 39
1 Contexto ................................................................................................................. 40
2 Descrição Técnica ................................................................................................... 41
2.1 Variáveis........................................................................................................... 41
2.2 Funções e procedimentos................................................................................ 43
2.2.1 Inserir registo no início da lista ligada (Med) ........................................... 43
2.2.2 Inserir registo no início da lista ligada (Principios)................................... 43
2.2.3 Inserir novo medicamento ....................................................................... 43
2.2.4 Inserir novo princípio ativo....................................................................... 44
2.2.5 Listar medicamentos ................................................................................ 44
2.2.6 Listar princípios ativos.............................................................................. 44
2.2.7 Gravar estrutura de medicamentos ......................................................... 44
2.2.8 Gravar estrutura de princípios ativos....................................................... 44
2.2.9 Carregar dados de medicamentos ........................................................... 44
2.2.10 Carregar dados de princípios ativos ......................................................... 44
2.2.11 Menu de princípios ativos ........................................................................ 44
2.2.12 Pesquisa de princípios ativos.................................................................... 45
2.2.13 Remover medicamento............................................................................ 45
2.2.14 Remover princípio ativo ........................................................................... 45
2.2.15 Pesquisar medicamentos por laboratório................................................ 45
2.2.16 Pesquisa por múltiplos critérios ............................................................... 45
2.2.17 Alterar dados de medicamento................................................................ 46
2.2.18 Alterar dados de princípios ativos............................................................ 46
2.2.19 Validar código........................................................................................... 46
vi
2.2.20 Validar número......................................................................................... 46
2.2.21 Validar laboratório.................................................................................... 46
2.2.22 Validar operações com estrutura medicamentos.................................... 46
2.2.23 Validar operações com estrutura princípios ativos.................................. 46
2.2.24 Selecionar critérios................................................................................... 47
2.2.25 Menu alterar medicamentos.................................................................... 47
2.2.26 Menu alterar princípios ativos.................................................................. 47
2.2.27 Inexistência de medicamentos................................................................. 47
2.2.28 Inexistência de princípios ativos............................................................... 47
2.2.29 Continuar.................................................................................................. 47
2.2.30 Navegação nos menus.............................................................................. 47
3 Desenvolvimento.................................................................................................... 48
3.1 Declarações...................................................................................................... 48
3.2 Inserir novo medicamento............................................................................... 48
3.3 Selecionar princípios ativos ............................................................................. 49
3.4 Pesquisa de princípios ativos........................................................................... 50
3.5 Remover medicamentos.................................................................................. 51
3.6 Pesquisa por múltiplos critérios ...................................................................... 52
3.7 Validar laboratório........................................................................................... 54
4 Testes e Resultados ................................................................................................ 55
4.1 Menu de opções principal ............................................................................... 55
4.2 Inserir novo medicamento............................................................................... 55
4.3 Alterar dados de medicamentos ..................................................................... 56
4.4 Pesquisa por laboratório.................................................................................. 56
4.5 Pesquisa por múltiplos critérios ...................................................................... 57
vii
4.6 Listar princípios ativos ..................................................................................... 57
5 Código fonte ........................................................................................................... 58
Capítulo III....................................................................................................................... 88
1 Contexto ................................................................................................................. 89
2 Descrição Técnica ................................................................................................... 90
2.1 Variáveis........................................................................................................... 90
2.2 Funções e procedimentos................................................................................ 92
2.2.1 Inserir atleta ............................................................................................. 92
2.2.2 Inserir tempos........................................................................................... 92
2.2.3 Introduzir dados do atleta........................................................................ 92
2.2.4 Gravar dados da estrutura (Atletas)......................................................... 92
2.2.5 Carregar dados para a estrutura (Atletas)................................................ 93
2.2.6 Carregar dados para a estrutura (ListaTempos)....................................... 93
2.2.7 Listar atletas inscritos............................................................................... 93
2.2.8 Consultar atletas por número .................................................................. 93
2.2.9 Consultar atletas por percurso................................................................. 93
2.2.10 Listar atletas por tempo de prova............................................................ 94
2.2.11 Listar atletas que terminaram a prova..................................................... 94
2.2.12 Validar número......................................................................................... 94
2.2.13 Validar operação....................................................................................... 94
2.2.14 Navegação nos menus e apresentação.................................................... 94
3 Desenvolvimento.................................................................................................... 95
3.1 Declarações...................................................................................................... 95
3.2 Introduzir atleta............................................................................................... 95
3.3 Carregar dados................................................................................................. 96
viii
3.4 Listar atletas..................................................................................................... 97
3.5 Validar número ................................................................................................ 97
3.6 Validar percurso............................................................................................... 97
3.7 Outros .............................................................................................................. 98
4 Testes e Resultados ................................................................................................ 99
4.1 Menu de opções .............................................................................................. 99
4.2 Inserir novo atleta............................................................................................ 99
4.3 Listar atletas inscritos .................................................................................... 100
4.4 Consultar atleta por número ......................................................................... 100
4.5 Consultar atleta por percurso........................................................................ 101
4.6 Listar atletas que terminaram a prova .......................................................... 101
5 Código fonte ......................................................................................................... 102
Conclusões.................................................................................................................... 117
Referências Bibliográficas............................................................................................. 118
1
Introdução
As linguagens de programação são uma forma de enviar instruções para um
computador ou processador, usando métodos padronizados.
Quando um programa de computador é criado, são usadas todo um conjunto de
regras sintáticas e semânticas que são caraterísticas da linguagem de programação
previamente selecionada para essa aplicação. Essas regras permitem ao programador
definir quais os dados onde o computador vai atuar, como serão armazenados esses
mesmos dados e todas as ações que o sistema deve tomar conforme as circunstâncias
o exigirem.
A um conjunto de regras sintáticas e semânticas designa-se de algoritmo. O
conjunto das palavras compostos de acordo com as regras referidas anteriormente,
designa-se de código fonte. Para um Software poder ser executado, esse código fonte
necessita ser traduzido para código máquina (binário) e posteriormente executado
pelo processador.
A principal vantagem do uso de linguagens de programação é o aumento de
produtividade para o programador, uma vez que lhe permite utilizar linguagens de alto
nível. Os processadores apenas trabalham com código máquina e se as aplicações
tivessem de ser desenvolvidas a este nível, os processos seriam demasiado morosos e
em alguns casos praticamente impossíveis de realizar. Ao utilizarem-se linguagens de
muito baixo nível também se torna extremamente complicado detetar os erros nos
algoritmos de implementação, devido à extrema complexidade dos códigos
associados. Utilizando a linguagem de alto nível, para além de se acelerar o processo
de criação de algoritmos porque a forma assemelha-se à linguagem humana,
facilmente se deteta os erros de implementação nos algoritmos com ajuda do
compilador que transforma o código fonte em código máquina antes do
processamento.
Introdução
2
1 Linguagem C
Uma das linguagens de programação mais utilizadas no mundo é a linguagem C.
Existem, outras ainda utilizadas atualmente tais como o Pascal, Fortran e Cobol. No
entanto será focada a linguagem C que é a linguagem de desenvolvimento deste
trabalho prático.
A linguagem C foi desenvolvida inicialmente entre 1969 e 1973 no AT&T Bell Lab
por Dennis Ritchie e Ken Thompson para a implementação do sistema UNIX (que era
originalmente escrito em Assembly).
A partir de 1973 com a adição do tipo de dados struct à linguagem C, esta
tornou-se suficientemente poderosa para a maioria dos núcleos do UNIX poderem ser
escritos em C. Assim, este foi um dos primeiros três sistemas a não serem
implementados em linguagem Assembly, abrindo as portas à linguagem C como
linguagem de programação preferencial.
Ao longo dos anos, a linguagem C foi sofrendo várias adaptações e melhorias,
sendo que atualmente se pode definir como uma linguagem de programação de alto
nível, compilada, estruturada, imperativa, procedural e padronizada. As suas
características mais importantes são:
Linguagem extremamente simples.
Bibliotecas de rotinas padronizadas, tais como funções matemáticas ou
manipulação de strings.
Paradigma de programação procedural.
Linguagem de pré-processamento que permite compilar vários ficheiros
de código fonte.
Uso de apontadores flexibiliza a linguagem.
Permite a inclusão de código Assembly no programa escrito em C.
O uso de estruturas (structs) permite que dados relacionados possam ser
manipulados como um todo.
Os tipos de dados da linguagem C podem ser do tipo inteiro (com ou sem sinal),
reais, carateres, estruturas e ainda muito importante do tipo apontadores.
Introdução
3
Os apontadores são um tipo de variável que guarda o endereço de memória de
outra variável. Na linguagem C, os apontadores possuem um valor reservado
designado NULL que significa que estes não estão a guardar no momento nenhum
endereço.
Os dados do tipo inteiro (int) servem para guardar números inteiros de valor
finito. Podem ser com ou sem sinal e o máximo e mínimo valor que se pode inserir é
limitado pela capacidade do processador de execução.
Os dados do tipo carater (char) ocupam 1 byte em memória independentemente
do sistema operativo e podem guardar carateres ou números inteiros. Através de
vetores de carateres é possível criar strings que são cadeias de carateres.
Os dados do tipo real (float) servem para guardar números de vírgula flutuante.
Estes dados podem ser ainda do tipo double float que apresentam o dobro da
capacidade de armazenamento.
2 Estruturas de dados
Na linguagem C são largamente usadas estruturas, que são grupos de variáveis
organizadas pelo programador e definidas através da criação de um novo tipo de
variável pela palavra reservada typedef.
Quando se desenvolve uma aplicação em qualquer linguagem de programação é
necessário desenvolver uma estrutura de dados que solucione o problema que se
pretende resolver.
Uma estrutura de dados é uma forma de armazenar e organizar os dados de
modo a que estes possam ser utilizados o mais eficazmente possível. O tipo de
estrutura selecionada pode depender da aplicação pretendida, sendo que as
estruturas mais comuns são as listas ligadas, as árvores binárias de procura, grafos, etc.
2.1 Listas ligadas simples
Uma lista ligada simples (LLS) é uma estrutura de dados dinâmicos, composta de
células que apontam para o próximo elemento da lista. Para criar uma lista ligada é
necessário saber o endereço do seu primeiro elemento, sendo que o ultimo elemento
Introdução
4
terá endereço NULL. A figura seguinte representa o esquema das ligações necessárias
para desenvolver uma lista ligada simples.
Figura 1 – Esquema de uma LLS.
Vantagens das LLS:
A inserção ou remoção de um elemento da lista ligada não implica mudar
outros elementos de lugar.
Quando se cria a lista, não é necessário definir o número máximo de
elementos que esta poderá ter, pois a memória pode ser alocada
dinamicamente.
Desvantagens das LLS:
Manipular a lista ligada pode ser perigoso, pois se a ligação entre os
elementos estiver mal feita, toda a lista ligada pode ser perdida.
Para aceder a um elemento nas posições finais da lista, é necessário
percorrer todas as posições iniciais.
2.2 Listas duplamente ligadas
Uma lista duplamente ligada (LDL) é uma derivação da lista ligada simples. O que
diferencia a lista duplamente ligada da lista ligada simples é que a lista duplamente
ligada apresenta dois apontadores, um para o endereço de memória do próximo
elemento da cadeia e outro apontador para o elemento anterior da cadeia. Como foi
visto anteriormente, na lista ligada simples apenas existe um apontador para o
endereço de memória do próximo elemento da cadeia.
A figura seguinte representa o esquema das ligações necessárias para
desenvolver uma lista duplamente ligada.
Introdução
5
Figura 2 – Esquema de uma LDL.
Vantagens das LDL:
Maior controlo dos dados presentes na lista ligada.
Existe menor risco de perda acidental dos dados.
Desvantagens das LDL:
Maior complexidade dos algoritmos.
Necessita de mais apontadores.
2.3 Árvores binárias de procura
Uma árvore binária de procura (ABP) é uma estrutura de dados que se baseada
em nós. Esta estrutura deve respeitar duas regras: os nós da subárvore esquerda
devem possuir uma chave com valor inferior ao nó raiz e todos os nós da subárvore
direita devem possuir uma chave com valor superior ao nó raiz. As árvores binárias de
procura possuem alguma terminologia associada que convém salientar:
Nós: representam os registos guardados na árvore.
Raiz: é o nó que fica no topo da árvore.
Filhos: são os nós que precedem os nós anteriores.
Pais: são os nós que antecedem os outros nós.
Folhas: são os nós terminais que não possuem ligação com outro nó.
Figura 3 – Esquema de uma ABP.
6
Capítulo I
Listas ligadas simples
Gestão de um arquivo de exames de diagnóstico médico
Cap. I
7
1 Contexto
Uma clínica médica, ao dispor de múltiplos serviços, departamentos e
especialidades, tem a necessidade de gerir todos os exames de diagnóstico que são
feitos para cada doente.
É necessário arquivar os exames realizados, numa determinada data, por um
determinado técnico. Entre outros serviços, é importante:
Consultar os exames realizados num determinado período de tempo;
Consultar os exames de um determinado doente;
Arquivar os exames realizados.
Pretende-se o desenvolvimento de uma aplicação em linguagem C, que efetue a
gestão desse arquivo de exames, através da utilização de listas ligadas simples.
A solução desenvolvida deverá possuir uma componente de interação com o
utilizador, bem como a capacidade de armazenar e carregar toda a informação através
de ficheiros.
Cap. I
8
2 Descrição Técnica
Para desenvolver o problema proposto, foi utilizada uma estrutura de dados
baseada numa lista ligada simples com nove variáveis para definir o registo Exames e
uma variável do tipo apontador para definir o endereço do registo seguinte na lista
ligada:
typedef struct Arquivo
{
int codigo, dia, mes, ano, identificacao;
char departamento[50], paciente[50], tecnico[50], resultados[100];
struct Arquivo *seguinte;
}
Exames;
2.1 Variáveis
A variável codigo deve receber um inteiro e guarda a identificação numérica do
exame inserido. A inserção deste código será limitada entre 1 e 9999 por opção. O
programa foi escrito de modo a inserir os registos no início da lista ligada. Assim o
utilizador deve tentar manter este código o mais ordenado possível, não fazendo
saltos entre valores de inserção. Através de restrições ao nível do código desenvolvido,
não será possível a introdução de códigos repetidos.
A variável departamento deve receber uma string de carateres (50 no máximo) e
vai descrever o exame ao dizer a que departamento pertence. Não foi considerado
relevante adicionar mais uma variável com o nome do exame realizado.
A variável paciente deve receber uma string de carateres (50 no máximo) e vai
guardar o nome do paciente que realizou o exame.
A variável identificacao deve receber um inteiro, e guarda o número do paciente
que realizou o exame. Este número pode ser um qualquer, sendo que foi pensado
inicialmente um conjunto de 9 algarismos referentes ao número do cartão de cidadão.
Será através deste número que serão efetuadas as pesquisas por paciente, como tal,
este número deverá ser o mais individualizado possível e o operador não deverá
utilizar o mesmo número em mais de um paciente.
Cap. I – Descrição Técnica
9
A variável tecnico deve receber uma string de carateres (50 no máximo) e vai
guardar o nome do funcionário que realizou o exame.
As variáveis dia, mes e ano devem receber inteiros e em conjunto vão guardar a
data de realização do exame. Estas variáveis terão restrições de inserção, para o
utilizador por engano não inserir dias ou meses incoerentes. Por opção, a inserção do
ano também foi limitada. Só serão considerados exames realizados a partir do ano
2000 e só será possível inserir até ao ano 2099, altura que o programa estará
obviamente obsoleto.
A variável resultados deve receber uma string de carateres (100 no máximo) e
vai guardar os resultados do paciente no exame realizado.
Finalmente a variável seguinte do tipo apontador para a estrutura Exames, será
o apontador para o endereço de memória do registo seguinte na lista ligada.
2.2 Funções e procedimentos
Para a implementação do programa, foi necessário desenvolver uma série de
funções e procedimentos. De seguida apresenta-se um pequeno resumo das rotinas
desenvolvidas pela ordem em que aparecem no código fonte.
2.2.1 Inserir registo no início da lista ligada
Convencionou-se que o último exame inserido devia ficar no topo da lista. Assim
optou-se pelo método de inserir no início da lista ligada. No entanto, quando se
carrega o ficheiro de texto, usando este método, os números dos registos acabariam
por ficar baralhados, como se vai explicar mais à frente. Assim é também utilizado o
inserir no fim da lista ligada mas somente após o carregar do ficheiro de texto. Este
método é usado quando os dados são inseridos manualmente pelo utilizador.
2.2.2 Inserir registo no fim da lista ligada
Como referido anteriormente, este método é utilizado após serem carregados os
dados do ficheiro de texto, de modo a ser mantida a ordem numérica (código) dos
registos. Caso fosse utilizado a opção inserir no final da lista ligada, não havia esta
necessidade como se vai explicar mais à frente. Assim esta função é complementar e é
chamada numa altura diferente da anterior.
Cap. I – Descrição Técnica
10
2.2.3 Introduzir dados num registo pelo utilizador
Este é um dos procedimentos principais do programa e permite que o utilizador
introduza novos registos na lista ligada. Além de pedir os dados a inserir ao utilizador,
possui limitações de introdução de dados e invoca outras funções e procedimentos
para permitir inserir na lista ligada e gravar.
2.2.4 Listar registos da lista ligada
Este procedimento a qualquer altura, percorre a lista ligada, uma vez que esta
está permanentemente atualizada, quer seja com dados inseridos pelo utilizador quer
com dados carregados do ficheiro de texto e imprime no monitor o conteúdo dos seus
diferentes registos.
2.2.5 Gravar lista ligada em ficheiro de texto
Este procedimento grava a lista ligada atualizada em formato de ficheiro de texto
sempre que é introduzido mais um registo pelo utilizador.
2.2.6 Carregar lista ligada do ficheiro de texto
Esta função é responsável por carregar os dados presentes no ficheiro de texto
para a lista ligada ao iniciar o programa. Os dados são inseridos na lista ligada através
da função inserir no fim da lista, como referido anteriormente.
2.2.7 Pesquisar exame por paciente
Este procedimento percorre a lista ligada, comparando o número de pesquisa ao
código dos registos até encontrar uma correspondência. Se esta existir, imprime na
consola os dados do registo. Se não encontrar qualquer correspondência devolve
mensagem informando que registo não existe no sistema. Este procedimento tal como
todos os que dependem de a lista ligada não estar vazia, será complementado com
outros procedimentos de controlo que impedirão que o procedimento seja executado
caso a lista ligada esteja vazia.
2.2.8 Pesquisar exames por período de tempo
Este procedimento é mais complexo e será demonstrado numa fase posterior.
Permite devolver os registos num período de tempo estabelecido pelo utilizador e tal
Cap. I – Descrição Técnica
11
como o procedimento anterior, caso a lista ligada se encontre vazia não vai ser
executado.
2.2.9 Alterar dados de um exame
Este procedimento que só será executado caso a lista ligada não se encontre
vazia, permite ao utilizador alterar os dados dos registos inseridos na lista ligada
diretamente a partir do programa. É pedido ao utilizador que selecione o código do
exame a alterar e posteriormente o dado pretendido.
2.2.10 Validar um código de exame
Esta função permite verificar se determinado código de exame já existe no
sistema. Assim será usada com duas funções: nas pesquisas por código de exame
permite rejeitar imediatamente caso ele não exista e controla que se possam inserir
códigos repetidos quando se está a criar um novo exame.
2.2.11 Validar operações com a lista ligada
Esta função é extremamente simples, mas altamente vantajosa, uma vez que
verifica se a lista ligada está vazia e serve como sistema de controlo para não deixar
correr outros procedimentos sobre uma lista ligada vazia.
2.2.12 Apresentar primeira página
Este é um procedimento simples que é invocado na função main que
simplesmente apresenta informações ao utilizador, nomeadamente o nome do
programa, alunos que o desenvolveram, o docente e outras informações úteis.
2.2.13 Apresentar menu
Esta função apresenta duas funcionalidades. A primeira é dar uma imagem
gráfica do menu, bem como as suas opções. A segunda é fazer a escolha da opção do
utilizador e retornar esse valor.
2.2.14 Correr o menu
Permite navegar por entre as opções do programa. Recebe a opção selecionada a
partir da função referenciada anteriormente e possui 5 seleções básicas para além da
opção de poder abandonar a aplicação.
Cap. I
12
3 Desenvolvimento
Para desenvolver o programa e para que este funcione corretamente, foi
necessário que todos os procedimentos e funções criados interagissem de forma
eficaz, sem erros e evitando situações do tipo “beco sem saída” que ocorrem quando
as aplicações bloqueiam ou ficam presas em estados sem retorno. O resultado final é o
código fonte que se encontra anexado a este relatório, sendo que nesta seção serão
explicadas algumas técnicas implementadas.
3.1 Bibliotecas
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <locale.h>
Estas instruções permitem incluir bibliotecas ao programa. Além das
necessidades normais de input/output (stdio.h), alocação de memória (stdlib.h),
manipulação de strings (string.h) e operações com diferentes tipos de variáveis
(ctype.h), foi necessário recorrer à biblioteca locale.h para poder incluir carateres
especiais em língua portuguesa, que serão largamente utilizados ao longo do
programa.
3.2 Declarações
Foi declarada globalmente uma variável ListaLigada do tipo apontador para a
estrutura Exames com o endereço inicial nulo. Esta declaração global torna possível o
seu uso em qualquer procedimento ou função sem a necessidade de voltar a declarar.
E desta forma sempre que uma operação for executada sobre a lista ligada esta estará
automaticamente atualizada.
Exames *ListaLigada = NULL;
Cap. I – Desenvolvimento
13
3.3 Métodos de inserção de dados
Foi definido que os dados inseridos deviam ficar no início da lista ligada e que era
importante manter ordenados os códigos. Se os dados fossem carregados do ficheiro
de texto através duma função inserir no início da lista, ia-se perder essa ordenação.
Exames *inserirFim (Exames *apt, int cod, char *dep, char *pac, int id,
char *tec, int d, int m, int a, char *res)
{
Exames *aux = apt;
Exames *novo;
novo = (Exames*) malloc (sizeof (Exames));
novo -> codigo = cod;
strcpy (novo -> departamento, dep);
strcpy (novo -> paciente, pac);
novo -> identificacao = id;
strcpy (novo -> tecnico, tec);
novo -> dia = d;
novo -> mes = m;
novo -> ano = a;
strcpy (novo -> resultados, res);
novo -> seguinte = NULL;
if (apt == NULL)
return (novo);
else
{
while (aux -> seguinte != NULL)
aux = aux -> seguinte;
aux -> seguinte = novo;
return (apt);
}
}
Assim foi criada uma função auxiliar de inserir no fim da lista ligada que só é
utilizada quando os dados são carregados do ficheiro de texto. De referir que este
problema de ordenação não ocorreria caso fosse utilizado sempre o inserir no fim da
lista ligada. No entanto não foi essa a opção adotada. O que se pretende evitar nesta
situação é:
Se o utilizador inserir 3 registos consecutivos: 1000, 1001, 1002…
Na lista ligada a ordem ficaria: 1002, 1001, 1000…
Ao gravar em ficheiro de texto: 1002, 1001, 1000…
Ao carregar usando inserir no início: 1000, 1001, 1002…
Se fosse inserido mais um registo: 1004, 1000, 1001, 1002…
Cap. I – Desenvolvimento
14
3.4 Restrições
Dentro do procedimento inserir exame vão existir algumas restrições como se
pode observar.
while (manter == 1)
{
printf ("CÓDIGO DO EXAME: ");
scanf ("%d", &cod);
fflush (stdin);
teste = validarCodigo (ListaLigada, cod);
if ((cod < 1) || (cod > 9999))
{
manter = 1;
printf ("nATENÇÃO! Introduza um código entre 1 e 9999nn");
}
else if (teste == 1)
{
manter = 1;
printf ("nATENÇÃO! Código já foi introduzidonn");
}
else
manter = 0;
}
Ao inserir o código do exame, o programa entra num ciclo e só sai se forem
verificadas as restrições: o código introduzido não ser repetido, não ser inferior a 1,
nem superior a 9999. Para verificar se o código já existe é usado o procedimento
validarCodigo que aparecerá posteriormente no corpo do programa.
while (manter == 1)
{
printf ("DIA: ");
scanf ("%d", &d);
fflush (stdin);
if ((d < 1) || (d > 31))
{
manter = 1;
printf ("nATENÇÃO! Introduza um dia entre 1 e 31nn");
}
else
manter = 0;
}
Este é outro tipo de restrição encontrada dentro do procedimento inserir exame,
que neste caso limita a introdução da variável dia. Mais uma vez o programa entra
num ciclo e só sairá se uma opção válida for introduzida que neste caso é um inteiro
entre 1 e 31. De notar que a variável que permite manter os ciclos é sempre a mesma,
uma vez que saindo destes, ela é reinicializada com o valor 1.
Cap. I – Desenvolvimento
15
3.5 Listar exames
O procedimento listar exames é extremamente simples. Uma vez que ele já
recebe a lista ligada pela definição da sua assinatura, existe uma condição que testa se
esta é ou não nula. Se for nula, invoca o procedimento naoExiste que apresenta uma
mensagem informando que não existem exames gravados. Se a lista ligada não estiver
vazia serão impressos no monitor, o conteúdo de todos os exames.
if (apt == NULL)
{
naoExiste ();
menu ();
}
else
{
printf ("n");
printf ("*****************************************************n");
printf ("* *n");
printf ("* EXAMES ARQUIVADOS *n");
printf ("* *n");
printf ("*****************************************************n");
3.6 Gravar exames
O procedimento gravar exames, permite a gravação em formato de ficheiro de
texto, de todos os dados presentes na lista ligada, impedindo estes de se perderem
quando o programa é terminado.
void gravar (Exames *apt)
{
FILE *ficheiro;
ficheiro = fopen ("Arquivo.txt", "w+");
if (ficheiro != NULL)
{
while (apt != NULL)
{
fprintf (ficheiro, "n%dn", apt -> codigo);
fprintf (ficheiro, "%sn", apt -> departamento);
fprintf (ficheiro, "%sn", apt -> paciente);
fprintf (ficheiro, "%dn", apt -> identificacao);
fprintf (ficheiro, "%sn", apt -> tecnico);
fprintf (ficheiro, "%dn", apt -> dia);
fprintf (ficheiro, "%dn", apt -> mes);
fprintf (ficheiro, "%dn", apt -> ano);
fprintf (ficheiro, "%s", apt -> resultados);
apt = apt -> seguinte;
}
}
fclose (ficheiro);
}
Cap. I – Desenvolvimento
16
3.7 Carregar exames
O procedimento carregar exames, vai permitir inserir os dados presentes no
ficheiro de texto na lista ligada, ao iniciar o programa. Se ao for executado o
procedimento ele não encontrar nenhum ficheiro de texto compatível, imprimirá uma
mensagem por cima do menu de opções durante a primeira utilização informando que
não existem exames guardados.
void carregar ()
{
FILE *ficheiro;
int cod, id, d, m, a;
char dep[50], pac[50], tec[50], res[100];
ficheiro = fopen ("Arquivo.txt", "r");
if (ficheiro != NULL)
{
while (!feof (ficheiro))
{
fscanf (ficheiro, "n%dn", &cod);
fscanf (ficheiro, " %[^n]", dep);
fscanf (ficheiro, " %[^n]", pac);
fscanf (ficheiro, "%dn", &id);
fscanf (ficheiro, " %[^n]", tec);
fscanf (ficheiro, "%dn", &d);
fscanf (ficheiro, "%dn", &m);
fscanf (ficheiro, "%dn", &a);
fscanf (ficheiro, " %[^n]", res);
ListaLigada=inserirFim(ListaLigada,cod,dep,pac,id,tec,d,m,a,res);
}
fclose (ficheiro);
}
else
printf ("nNão foram carregados exames!n");
}
3.8 Pesquisa de exames por paciente
O procedimento pesquisar exame por paciente é um dos vários que é controlado
através da função validarOperacao. Neste caso não era fundamental recorrer a este
método, uma vez que ele recebe a lista ligada na sua assinatura. No entanto, este
passou a ser o método de testar se o procedimento devia ser ou não executado, sendo
que noutros procedimentos ele é mesmo necessário, uma vez que não recebem a lista
ligada na assinatura. Assim, se a função retornar -1 significa que a lista ligada se
encontra vazia e o procedimento imprime uma mensagem informando que não
existem exames. Se a função retornar 1 executa o procedimento.
Cap. I – Desenvolvimento
17
void pesquisaPaciente (Exames *apt)
{
int chave, teste2 = 1;
char escolha2;
system ("cls");
teste2 = validarOperacao (ListaLigada);
if (teste2 == -1)
{
naoExiste ();
menu ();
}
else
{
Continuando no procedimento pesquisar exame por paciente, é solicitado uma
chave de pesquisa ao utilizador. Seguidamente o programa vai correr a lista ligada
enquanto essa chave for diferente das identificações dos registos. Quando encontrar
uma correspondência, se o registo não estiver vazio imprime o seu conteúdo.
printf ("Identificação: ");
scanf ("%d", &chave);
fflush (stdin);
while ((apt != NULL) && (apt -> identificacao != chave))
apt = apt -> seguinte;
if (apt != NULL)
{
printf ("nn");
printf ("CÓDIGO DO EXAME: %dn", apt -> codigo);
printf ("DEPARTAMENTO: %sn", apt -> departamento);
printf ("NOME DO PACIENTE: %sn", apt -> paciente);
printf ("IDENTIFICAÇÃO DO PACIENTE: %dn", apt -> identificacao);
printf ("TÉCNICO RESPONSÁVEL: %sn", apt -> tecnico);
printf ("DATA: %d-%d-%dn", apt -> dia, apt -> mes, apt -> ano);
printf ("RESULTADOS: %snn", apt -> resultados);
}
else
printf ("nnEXAME INEXISTENTEnn");
3.9 Pesquisa de exames por data
Na pesquisa por data, pretende-se listar os exames realizados entre determinado
período de tempo.
void pesquisaData (Exames *apt)
{
int chaveDiaInf, chaveMesInf, chaveAnoInf, inf;
int chaveDiaSup, chaveMesSup, chaveAnoSup, sup;
int manter2 = 1, teste3 = 0, cnt = 0;
char escolha3;
Cap. I – Desenvolvimento
18
A solução encontrada foi limitar esse período através de duas chaves: uma
inferior e outra superior. Assim tem de ser definidos os dias, meses e anos tanto da
chave inferior como da superior.
inf = (chaveAnoInf*365) + (chaveMesInf*31) + chaveDiaInf;
sup = (chaveAnoSup*365) + (chaveMesSup*31) + chaveDiaSup;
Após o utilizador inserir os dados para completar as chaves, que são compostas
por limitações de inserção para garantir que não se inserem datas irreais, o programa
vai transformar as datas numa chave. Para a obtenção dessa chave a melhor solução
encontrada e que provou estar imune a falhas foi transformar toda a data em número
de dias. Para isso multiplica-se o ano por 365, o mês por 31, e a estas duas variáveis
soma-se o valor do dia. Assim garante-se que nenhuma chave possa ser repetida.
while (apt != NULL)
{
if (((((apt->ano)*365) + ((apt->mes)*31) + (apt->dia)) >= inf) &&
((((apt->ano)*365) + ((apt->mes)*31) + (apt->dia)) <= sup))
{
printf ("nn");
printf ("CÓDIGO DO EXAME: %dn", apt -> codigo);
printf ("DEPARTAMENTO: %sn", apt -> departamento);
printf ("NOME DO PACIENTE: %sn", apt -> paciente);
printf ("IDENTIFICAÇÃO DO PACIENTE: %dn", apt -> identificacao);
printf ("TÉCNICO RESPONSÁVEL: %sn", apt -> tecnico);
printf ("DATA: %d-%d-%dn", apt -> dia, apt -> mes, apt -> ano);
printf ("RESULTADOS: %snn", apt -> resultados);
cnt = cnt++;
}
apt = apt -> seguinte;
}
if (cnt == 0)
printf ("nnNÃO EXISTEM EXAMES NESTE PERÍODO DE TEMPOnn");
De seguida, enquanto a lista ligada não chegar ao fim, vai ser comparada a chave
de cada registo para ver se fica enquadrada entre as duas chaves criadas. Por cada
equivalência encontrada é impresso no monitor o conteúdo do registo.
3.10 Alterar exames
O procedimento alterar vai permitir substituir dados nos registos da lista ligada,
se esta não for vazia.
Este procedimento contém várias das restrições anteriores, não apresentando
nada de novo, sendo que a mais importante é que se o código do exame a alterar não
Cap. I – Desenvolvimento
19
for validado o utilizador tem duas opções: recomeçar, procurando um código válido ou
abandonar o procedimento.
void alterar (Exames *apt)
{
int _cod, _id, _d, _m, _a;
char _dep[50], _pac[50], _tec[50], _res[100];
int manter3 = 1, modificar = 0, teste4 = 0, teste5 = 0;
char escolha4;
teste4 = validarOperacao (ListaLigada);
if (teste4 == -1)
{
naoExiste ();
menu ();
}
else
{
printf ("*****************************************************n");
printf ("* *n");
printf ("* ALTERAR DADOS DE EXAME *n");
printf ("* *n");
printf ("*****************************************************n");
while (manter3 == 1)
{
printf ("n");
printf ("Código: ");
scanf ("%d", &_cod);
fflush (stdin);
teste5 = validarCodigo (ListaLigada, _cod);
if (teste5 == 0)
{
printf ("nnCódigo não se encontra registadonn");
printf ("Deseja continuar? [S/N]? ");
scanf ("%s", &escolha4);
3.11 Validar código
Como já antes referido esta função que é várias vezes invocada, permite verificar
se um determinado código já se encontra utilizado na lista ligada. Percorre a lista
ligada e se encontrar uma equivalência retorna 1. Caso contrário, retorna 0.
int validarCodigo (Exames *apt, int test)
{
while (apt != NULL)
{
if (apt -> codigo == test)
return (1);
apt = apt -> seguinte;
}
return (0);
}
Cap. I – Desenvolvimento
20
3.12 Validar operação
Este procedimento que é largamente utilizado, testa se a lista ligada é ou não
vazia. Se for nula, devolve -1. Caso contrário devolve 1.
int validarOperacao (Exames *apt)
{
if (apt == NULL)
return (-1);
else
return (1);
}
3.13 Função main
Na função main foi necessário incluir a instrução setlocale configurada para
“Portuguese” de modo a permitir a inclusão de carateres especiais em língua
portuguesa na escrita.
int main (void)
{
setlocale (LC_ALL,"Portuguese");
capa ();
carregar ();
menu ();
return (0);
}
Cap. I
21
4 Testes e Resultados
4.1 Página inicial
A página inicial apresenta variadas informações, tais como o nome de quem
desenvolveu o trabalho, o nome da aplicação, docente e unidade curricular para a qual
esta foi desenvolvida.
Figura 4 – Página inicial.
4.2 Menu
O menu de opções é um dos aspetos mais importantes do programa, uma vez
que permite navegar entre as diversas funcionalidades e ao mesmo tempo apresentar
um ambiente gráfico agradável ao utilizador.
Figura 5 – Menu de opções.
Cap. I – Testes e Resultados
22
4.3 Listar todos os exames
A opção listar todos os exames, imprime no monitor os dados de todos os
exames arquivados, sendo que o último exame inserido aparecerá sempre no topo da
lista. É a forma mais rápida de ter acesso aos exames guardados no programa.
Figura 6 – Listar todos os exames.
4.4 Pesquisa por paciente
A pesquisa por paciente é utilizada quando se pretende procurar um exame
associado a um paciente para o qual previamente se conhece o número de
identificação. No final de cada pesquisa é solicitado ao utilizador se pretende efetuar
uma nova pesquisa.
Figura 7 – Pesquisa por paciente.
Cap. I – Testes e Resultados
23
4.5 Pesquisa por data
A pesquisa por período de tempo permite encontrar exames realizados num
determinado período de tempo definido pelo utilizador. Caso não seja encontrado o
pretendido, no final é solicitado ao utilizador se deseja continuar.
Figura 8 – Pesquisa por período de tempo.
4.6 Inserir novo exame
Os dados de um novo exame são inseridos consecutivamente, com a opção de
introduzir os dados de vários pacientes.
Figura 9 – Inserir novo exame.
Cap. I
24
5 Código fonte
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <locale.h>
typedef struct Arquivo
{
int codigo, dia, mes, ano, identificacao;
char departamento[50], paciente[50], tecnico[50], resultados[100];
struct Arquivo *seguinte;
}
Exames;
Exames *ListaLigada = NULL;
void inserirExame ();
void listar (Exames *apt);
void gravar (Exames *apt);
void carregar ();
void pesquisaPaciente (Exames *apt);
void pesquisaData (Exames *apt);
void alterar (Exames *apt);
int validarCodigo (Exames *apt, int test);
int validarOperacao (Exames *apt);
void menuAlterar ();
void naoExiste ();
void continuar ();
void capa ();
int fmenu ();
void menu ();
Exames *inserirInicio (Exames *apt, int cod, char *dep, char *pac, int id,
char *tec, int d, int m, int a, char *res)
{
Exames *novo;
novo = (Exames*) malloc (sizeof (Exames));
novo -> codigo = cod;
strcpy (novo -> departamento, dep);
strcpy (novo -> paciente, pac);
novo -> identificacao = id;
strcpy (novo -> tecnico, tec);
novo -> dia = d;
novo -> mes = m;
novo -> ano = a;
strcpy (novo -> resultados, res);
novo -> seguinte = apt;
return (novo);
}
Cap. I – Código fonte
25
Exames *inserirFim (Exames *apt, int cod, char *dep, char *pac, int id,
char *tec, int d, int m, int a, char *res)
{
Exames *aux = apt;
Exames *novo;
novo = (Exames*) malloc (sizeof (Exames));
novo -> codigo = cod;
strcpy (novo -> departamento, dep);
strcpy (novo -> paciente, pac);
novo -> identificacao = id;
strcpy (novo -> tecnico, tec);
novo -> dia = d;
novo -> mes = m;
novo -> ano = a;
strcpy (novo -> resultados, res);
novo -> seguinte = NULL;
if (apt == NULL)
return (novo);
else
{
while (aux -> seguinte != NULL)
aux = aux -> seguinte;
aux -> seguinte = novo;
return (apt);
}
}
void inserirExame ()
{
int cod, id, d, m, a;
char dep[50], pac[50], tec[50], res[100];
int manter = 1, teste = 0;
char escolha;
system ("cls");
printf ("n");
printf ("*******************************************************n");
printf ("* *n");
printf ("* INSERIR DADOS DO EXAME *n");
printf ("* *n");
printf ("*******************************************************n");
printf ("n");
while (manter == 1)
{
printf ("CÓDIGO DO EXAME: ");
scanf ("%d", &cod);
fflush (stdin);
teste = validarCodigo (ListaLigada, cod);
if ((cod < 1) || (cod > 9999))
{
manter = 1;
printf ("nATENÇÃO! Introduza um código entre 1 e 9999nn");
}
else if (teste == 1)
Cap. I – Código fonte
26
{
manter = 1;
printf ("nATENÇÃO! Código já foi introduzidonn");
}
else
manter = 0;
}
manter = 1;
printf ("nDEPARTAMENTO: ");
gets (dep);
fflush (stdin);
printf ("nNOME DO PACIENTE: ");
gets (pac);
fflush (stdin);
printf ("nIDENTIFICAÇÃO DO PACIENTE: ");
scanf ("%d", &id);
fflush (stdin);
printf ("nTÉCNICO RESPONSÁVEL: ");
gets (tec);
fflush (stdin);
printf ("nDATA DO EXAMEn");
while (manter == 1)
{
printf ("DIA: ");
scanf ("%d", &d);
fflush (stdin);
if ((d < 1) || (d > 31))
{
manter = 1;
printf ("nATENÇÃO! Introduza um dia entre 1 e 31nn");
}
else
manter = 0;
}
manter = 1;
while (manter == 1)
{
printf ("MÊS: ");
scanf ("%d", &m);
fflush (stdin);
if ((m < 1) || (m > 12))
{
manter = 1;
printf ("nATENÇÃO! Introduza um mês entre 1 e 12nn");
}
else
manter = 0;
}
manter = 1;
while (manter == 1)
{
printf ("ANO: ");
scanf ("%d", &a);
Cap. I – Código fonte
27
fflush (stdin);
if ((a < 2000) || (a > 2099))
{
manter = 1;
printf ("nATENÇÃO! Introduza um ano entre 2000 e 2099nn");
}
else
manter = 0;
}
manter = 1;
printf ("nRESULTADOS: ");
gets (res);
fflush (stdin);
ListaLigada = inserirInicio (ListaLigada,cod,dep,pac,id,tec,d,m,a,res);
gravar (ListaLigada);
printf ("nnDeseja continuar? [S/N] ");
scanf ("%s", &escolha);
fflush (stdin);
if ((escolha == 'S') || (escolha == 's'))
{
system ("cls");
inserirExame ();
}
else
{
system ("cls");
menu ();
}
}
void listar (Exames *apt)
{
system ("cls");
if (apt == NULL)
{
naoExiste ();
menu ();
}
else
{
printf ("n");
printf ("*****************************************************n");
printf ("* *n");
printf ("* EXAMES ARQUIVADOS *n");
printf ("* *n");
printf ("*****************************************************n");
printf ("n");
while (apt != NULL)
{
printf ("n");
printf ("CÓDIGO DO EXAME: %dn", apt -> codigo);
printf ("DEPARTAMENTO: %sn", apt -> departamento);
Cap. I – Código fonte
28
printf ("NOME DO PACIENTE: %sn", apt -> paciente);
printf ("IDENTIFICAÇÃO DO PACIENTE: %dn", apt -> identificacao);
printf ("TÉCNICO RESPONSÁVEL: %sn", apt -> tecnico);
printf ("DATA: %d-%d-%dn", apt -> dia, apt -> mes, apt -> ano);
printf ("RESULTADOS: %snn", apt -> resultados);
apt = apt -> seguinte;
}
}
continuar ();
menu ();
}
void gravar (Exames *apt)
{
FILE *ficheiro;
ficheiro = fopen ("Arquivo.txt", "w+");
if (ficheiro != NULL)
{
while (apt != NULL)
{
fprintf (ficheiro, "n%dn", apt -> codigo);
fprintf (ficheiro, "%sn", apt -> departamento);
fprintf (ficheiro, "%sn", apt -> paciente);
fprintf (ficheiro, "%dn", apt -> identificacao);
fprintf (ficheiro, "%sn", apt -> tecnico);
fprintf (ficheiro, "%dn", apt -> dia);
fprintf (ficheiro, "%dn", apt -> mes);
fprintf (ficheiro, "%dn", apt -> ano);
fprintf (ficheiro, "%s", apt -> resultados);
apt = apt -> seguinte;
}
}
fclose (ficheiro);
}
void carregar ()
{
FILE *ficheiro;
int cod, id, d, m, a;
char dep[50], pac[50], tec[50], res[100];
ficheiro = fopen ("Arquivo.txt", "r");
if (ficheiro != NULL)
{
while (!feof (ficheiro))
{
fscanf (ficheiro, "n%dn", &cod);
fscanf (ficheiro, " %[^n]", dep);
fscanf (ficheiro, " %[^n]", pac);
fscanf (ficheiro, "%dn", &id);
fscanf (ficheiro, " %[^n]", tec);
fscanf (ficheiro, "%dn", &d);
fscanf (ficheiro, "%dn", &m);
fscanf (ficheiro, "%dn", &a);
fscanf (ficheiro, " %[^n]", res);
Cap. I – Código fonte
29
ListaLigada=inserirFim(ListaLigada,cod,dep,pac,id,tec,d,m,a,res);
}
fclose (ficheiro);
}
else
printf ("nNão foram carregados exames!n");
}
void pesquisaPaciente (Exames *apt)
{
int chave, teste2 = 1;
char escolha2;
system ("cls");
teste2 = validarOperacao (ListaLigada);
if (teste2 == -1)
{
naoExiste ();
menu ();
}
else
{
printf ("n");
printf ("*****************************************************n");
printf ("* *n");
printf ("* PESQUISAR EXAME POR PACIENTE *n");
printf ("* *n");
printf ("*****************************************************n");
printf ("n");
printf ("Identificação: ");
scanf ("%d", &chave);
fflush (stdin);
while ((apt != NULL) && (apt -> identificacao != chave))
apt = apt -> seguinte;
if (apt != NULL)
{
printf ("nn");
printf ("CÓDIGO DO EXAME: %dn", apt -> codigo);
printf ("DEPARTAMENTO: %sn", apt -> departamento);
printf ("NOME DO PACIENTE: %sn", apt -> paciente);
printf ("IDENTIFICAÇÃO DO PACIENTE: %dn", apt -> identificacao);
printf ("TÉCNICO RESPONSÁVEL: %sn", apt -> tecnico);
printf ("DATA: %d-%d-%dn", apt -> dia, apt -> mes, apt -> ano);
printf ("RESULTADOS: %snn", apt -> resultados);
}
else
printf ("nnEXAME INEXISTENTEnn");
printf ("nDeseja efetuar nova pesquisa? [S/N]? ");
scanf ("%s", &escolha2);
fflush (stdin);
if ((escolha2 == 'S') || (escolha2 == 's'))
{
system ("cls");
pesquisaPaciente (ListaLigada);
}
Cap. I – Código fonte
30
else
{
system ("cls");
menu ();
}
}
}
void pesquisaData (Exames *apt)
{
int chaveDiaInf, chaveMesInf, chaveAnoInf, inf;
int chaveDiaSup, chaveMesSup, chaveAnoSup, sup;
int manter2 = 1, teste3 = 0, cnt = 0;
char escolha3;
system ("cls");
teste3 = validarOperacao (ListaLigada);
if (teste3 == -1)
{
naoExiste ();
menu ();
}
else
{
printf ("n");
printf ("*****************************************************n");
printf ("* *n");
printf ("* PESQUISAR EXAMES POR PERÍODO DE TEMPO... *n");
printf ("* *n");
printf ("*****************************************************n");
printf ("n");
printf ("Data Inicialn");
while (manter2 == 1)
{
printf ("Dia: ");
scanf ("%d", &chaveDiaInf);
fflush (stdin);
if ((chaveDiaInf < 1) || (chaveDiaInf > 31))
{
manter2 = 1;
printf ("nATENÇÃO! Introduza um dia entre 1 e 31nn");
}
else
manter2 = 0;
}
manter2 = 1;
while (manter2 == 1)
{
printf ("Mês: ");
scanf ("%d", &chaveMesInf);
fflush (stdin);
if ((chaveMesInf < 1) || (chaveMesInf > 12))
{
manter2 = 1;
Cap. I – Código fonte
31
printf ("nATENÇÃO! Introduza um mês entre 1 e 12nn");
}
else
manter2 = 0;
}
manter2 = 1;
while (manter2 == 1)
{
printf ("Ano: ");
scanf ("%d", &chaveAnoInf);
fflush (stdin);
if ((chaveAnoInf < 2000) || (chaveAnoInf > 2099))
{
manter2 = 1;
printf ("nATENÇÃO! Introduza um ano entre 2000 e 2099nn");
}
else
manter2 = 0;
}
manter2 = 1;
printf ("n");
printf ("Data Finaln");
while (manter2 == 1)
{
printf ("Dia: ");
scanf ("%d", &chaveDiaSup);
fflush (stdin);
if ((chaveDiaSup < 1) || (chaveDiaSup > 31))
{
manter2 = 1;
printf ("nATENÇÃO! Introduza um dia entre 1 e 31nn");
}
else
manter2 = 0;
}
manter2 = 1;
while (manter2 == 1)
{
printf ("Mês: ");
scanf ("%d", &chaveMesSup);
fflush (stdin);
if ((chaveMesSup < 1) || (chaveMesSup > 12))
{
manter2 = 1;
printf ("nATENÇÃO! Introduza um mês entre 1 e 12nn");
}
else
manter2 = 0;
}
manter2 = 1;
Cap. I – Código fonte
32
while (manter2 == 1)
{
printf ("Ano: ");
scanf ("%d", &chaveAnoSup);
fflush (stdin);
if ((chaveAnoSup < 2000) || (chaveAnoSup > 2099))
{
manter2 = 1;
printf ("nATENÇÃO! Introduza um ano entre 2000 e 2099nn");
}
else
manter2 = 0;
}
manter2 = 1;
inf = (chaveAnoInf*365) + (chaveMesInf*31) + chaveDiaInf;
sup = (chaveAnoSup*365) + (chaveMesSup*31) + chaveDiaSup;
while (apt != NULL)
{
if (((((apt->ano)*365) + ((apt->mes)*31) + (apt->dia)) >= inf) &&
((((apt->ano)*365) + ((apt->mes)*31) + (apt->dia)) <= sup))
{
printf ("nn");
printf ("CÓDIGO DO EXAME: %dn", apt -> codigo);
printf ("DEPARTAMENTO: %sn", apt -> departamento);
printf ("NOME DO PACIENTE: %sn", apt -> paciente);
printf ("IDENTIFICAÇÃO DO PACIENTE: %dn", apt -> identificacao);
printf ("TÉCNICO RESPONSÁVEL: %sn", apt -> tecnico);
printf ("DATA: %d-%d-%dn", apt -> dia, apt -> mes, apt -> ano);
printf ("RESULTADOS: %snn", apt -> resultados);
cnt = cnt++;
}
apt = apt -> seguinte;
}
if (cnt == 0)
printf ("nnNÃO EXISTEM EXAMES NESTE PERÍODO DE TEMPOnn");
printf ("nDeseja efetuar nova pesquisa? [S/N]? ");
scanf ("%s", &escolha3);
fflush (stdin);
if ((escolha3 == 'S') || (escolha3 == 's'))
{
system ("cls");
pesquisaData (ListaLigada);
}
else
{
system ("cls");
menu ();
}
}
}
Cap. I – Código fonte
33
void alterar (Exames *apt)
{
int _cod, _id, _d, _m, _a;
char _dep[50], _pac[50], _tec[50], _res[100];
int manter3 = 1, modificar = 0, teste4 = 0, teste5 = 0;
char escolha4;
system ("cls");
teste4 = validarOperacao (ListaLigada);
if (teste4 == -1)
{
naoExiste ();
menu ();
}
else
{
printf ("n");
printf ("*****************************************************n");
printf ("* *n");
printf ("* ALTERAR DADOS DE EXAME *n");
printf ("* *n");
printf ("*****************************************************n");
while (manter3 == 1)
{
printf ("n");
printf ("Código: ");
scanf ("%d", &_cod);
fflush (stdin);
teste5 = validarCodigo (ListaLigada, _cod);
if (teste5 == 0)
{
printf ("nnCódigo não se encontra registadonn");
printf ("Deseja continuar? [S/N]? ");
scanf ("%s", &escolha4);
fflush (stdin);
if ((escolha4 == 'S') || (escolha4 == 's'))
manter3 = 1;
else
{
system ("cls");
menu ();
}
}
else
{
manter3 = 0;
system ("cls");
}
}
manter3 = 1;
menuAlterar ();
Cap. I – Código fonte
34
while (manter3 == 1)
{
printf ("Selecione opção: ");
scanf ("%d", &modificar);
fflush (stdin);
if ((modificar < 1) || (modificar > 6))
{
manter3 = 1;
printf ("nIntroduza opção entre 1 e 6nn");
}
else
manter3 = 0;
}
while ((apt != NULL) && (apt -> codigo != _cod))
apt = apt -> seguinte;
if ((apt != NULL) && (modificar == 1))
{
printf ("nNovo departamento: ");
gets (_dep);
fflush (stdin);
strcpy (apt -> departamento, _dep);
}
else if ((apt != NULL) && (modificar == 2))
{
printf ("nNovo paciente: ");
gets (_pac);
fflush (stdin);
strcpy (apt -> paciente, _pac);
}
else if ((apt != NULL) && (modificar == 3))
{
printf ("nNova identificação: ");
scanf ("%d", &_id);
fflush (stdin);
apt -> identificacao = _id;
}
else if ((apt != NULL) && (modificar == 4))
{
printf ("nNovo técnico: ");
gets (_tec);
fflush (stdin);
strcpy (apt -> tecnico, _tec);
}
else if ((apt != NULL) && (modificar == 5))
{
printf ("nNova datan");
printf ("Dia: ");
scanf ("%d", &_d);
fflush (stdin);
printf ("Mês: ");
scanf ("%d", &_m);
fflush (stdin);
printf ("Ano: ");
scanf ("%d", &_a);
fflush (stdin);
apt -> dia = _d;
apt -> mes = _m;
apt -> ano = _a;
}
Cap. I – Código fonte
35
else if ((apt != NULL) && (modificar == 6))
{
printf ("nNovos resultados: ");
gets (_res);
fflush (stdin);
strcpy (apt -> resultados, _res);
}
printf ("nnEXAME ALTERADO!n");
gravar (ListaLigada);
printf ("nnDeseja efetuar nova alteração? [S/N]? ");
scanf ("%s", &escolha4);
fflush (stdin);
if ((escolha4 == 'S') || (escolha4 == 's'))
{
system ("cls");
alterar (ListaLigada);
}
else
{
system ("cls");
menu ();
}
}
}
int validarCodigo (Exames *apt, int test)
{
while (apt != NULL)
{
if (apt -> codigo == test)
return (1);
apt = apt -> seguinte;
}
return (0);
}
int validarOperacao (Exames *apt)
{
if (apt == NULL)
return (-1);
else
return (1);
}
void menuAlterar ()
{
printf ("n");
printf ("*******************************************************n");
printf ("* *n");
printf ("* ALTERAR DADOS DE EXAME *n");
printf ("* *n");
printf ("*******************************************************n");
printf ("-----------------------------------------------------------n");
Cap. I – Código fonte
36
printf ("| 1 | Departamento |n");
printf ("-----------------------------------------------------------n");
printf ("| 2 | Paciente |n");
printf ("-----------------------------------------------------------n");
printf ("| 3 | Identificação do paciente |n");
printf ("-----------------------------------------------------------n");
printf ("| 4 | Técnico responsável |n");
printf ("-----------------------------------------------------------n");
printf ("| 5 | Data do exame |n");
printf ("-----------------------------------------------------------n");
printf ("| 6 | Resultados |n");
printf ("-----------------------------------------------------------n");
printf ("n");
}
void naoExiste ()
{
printf ("nn");
printf ("*******************************************************n");
printf ("* *n");
printf ("* NÃO EXISTEM EXAMES ARQUIVADOS *n");
printf ("* *n");
printf ("*******************************************************n");
printf ("n");
printf ("n");
printf ("Prima uma tecla para continuar...n");
getchar ();
system ("cls");
}
void continuar ()
{
printf ("nPrima uma tecla para continuar...n");
getchar ();
system ("cls");
}
void capa ()
{
printf ("n");
printf ("-------------------------------------------------------n");
printf ("| |n");
printf ("| TRABALHO PRÁTICO DE PROGRAMAÇÃO I |n");
printf ("| |n");
printf ("| Aplicação A |n");
printf ("| |n");
printf ("-------------------------------------------------------n");
printf ("| |n");
printf ("| ALUNOS: Paulo Lima Nº 6522 |n");
printf ("| |n");
printf ("-------------------------------------------------------n");
printf ("| |n");
printf ("| DOCENTE: João Carlos Silva |n");
printf ("| |n");
printf ("-------------------------------------------------------n");
printf (" n");
printf ("Prima uma tecla para continuar...n");
getchar ();
fflush (stdin);
Cap. I – Código fonte
37
system ("cls");
}
int fmenu ()
{
char op[10];
int manter4 = 1, i = 0, t = 0, opc = 0;
while (manter4 == 1)
{
printf (" nn");
printf ("----------------------------------------------------n");
printf ("| | |n");
printf ("| MENU | SISTEMA DE GESTÃO DE EXAMES MÉDICOS |n");
printf ("| | |n");
printf ("----------------------------------------------------n");
printf ("| 1 | Inserir novo exame |n");
printf ("----------------------------------------------------n");
printf ("| 2 | Consultar exame por paciente |n");
printf ("----------------------------------------------------n");
printf ("| 3 | Consultar exames por período de tempo |n");
printf ("----------------------------------------------------n");
printf ("| 4 | Listar todos os exames |n");
printf ("----------------------------------------------------n");
printf ("| 5 | Alterar dados de exame |n");
printf ("----------------------------------------------------n");
printf ("| 0 | Sair |n");
printf ("----------------------------------------------------n");
printf ("n");
printf ("Seleccionar uma opção: ");
fflush (stdin);
gets (op);
t = strlen (op);
for (i = 0; i < t; i++)
{
if (isdigit (op[i]) != 0)
manter4 = 0;
else
{
manter4 = 1;
printf ("nATENÇÃO! Introduza um númeron");
getchar ();
system ("cls");
}
}
if (manter4 == 0)
{
opc = atoi (op);
if ((opc!=1) && (opc!=2) && (opc!=3) && (opc!=4) && (opc!=5) && (opc!=0))
{
manter4 = 1;
printf ("nATENÇÃO! Introduza uma opção entre 0 e 5n");
getchar ();
system ("cls");
opc = 0;
}
Cap. I – Código fonte
38
else
manter4 = 0;
}
}
return (opc);
}
void menu ()
{
int opcao = 0;
opcao = fmenu ();
while (opcao != 0)
{
switch (opcao)
{
case 1:
inserirExame ();
break;
case 2:
pesquisaPaciente (ListaLigada);
break;
case 3:
pesquisaData (ListaLigada);
break;
case 4:
listar (ListaLigada);
break;
case 5:
alterar (ListaLigada);
break;
}
}
if (opcao == 0)
exit (0);
}
int main (void)
{
setlocale (LC_ALL,"Portuguese");
capa ();
carregar ();
menu ();
return (0);
}
39
Capítulo II
Listas duplamente ligadas
Gestão de um simposium de medicamentos genéricos
Cap. II
40
1 Contexto
Uma empresa farmacêutica pretende desenvolver um simpósio de
medicamentos genéricos para fornecer a médicos de várias especialidades. Este
simpósio deverá conter toda a informação que o médico considere útil e necessária,
tais como indicações, contraindicações, posologia, princípio ativo, composição, outros
medicamentos com o mesmo princípio ativo, etc.
Os medicamentos devem estar agrupados por laboratórios, sendo possível:
Registar novo medicamento.
Registar novo princípio ativo.
Consultar por múltiplos critérios.
Remoção de medicamento.
Pretende-se o desenvolvimento de uma aplicação em linguagem C, que efetue a
gestão desse simpósio, através da utilização de listas duplamente ligadas.
A solução desenvolvida deverá possuir uma componente de interação com o
utilizador, bem como a capacidade de armazenar e carregar toda a informação através
de ficheiros.
Cap. II
41
2 Descrição Técnica
Para desenvolver esta segunda aplicação proposta e de modo a dar uma solução
o mais eficaz possível, foram utilizadas duas estruturas de dados baseadas em listas
duplamente ligadas. A primeira estrutura foi denominada de Med e desenvolvida para
guardar os dados associados aos medicamentos genéricos.
typedef struct Simposium
{
int codigo;
char nome[50], principioAtivo[50], outrosMedicamentos[100], laboratorio[50];
char composicao[50], posologia[50], indicacoes[50], contraIndicacoes[50];
struct Simposium *anterior;
struct Simposium *seguinte;
}
Med;
A segunda estrutura foi denominada de Principios e foi desenvolvida com o
intuito de guardar os princípios ativos autonomamente, de modo que estes possam
sempre que requeridos ser chamados a ser inseridos na estrutura principal.
typedef struct Generico
{
int numero;
char designacao[50], descricao[100];
struct Generico *ant;
struct Generico *seg;
}
Principios;
2.1 Variáveis
A variável codigo deve receber um inteiro e guarda a identificação numérica do
medicamento inserido. A inserção deste código será limitada entre 1 e 9999 por opção
e não poderão ser introduzidos códigos repetidos. O programa foi escrito de modo a
inserir os registos no início da lista ligada, sendo que para este caso a ordenação não é
importante.
A variável nome deve receber uma string de carateres (50 no máximo) e vai
guardar o nome do medicamento inserido no sistema.
A variável principioAtivo deve receber uma string de carateres (50 no máximo) e
vai indicar o princípio ativo que está associado ao medicamento. Este princípio ativo
pode ser introduzido diretamente pelo utilizador, ou escolhido através de um menu
caso a segunda estrutura (Princípios Ativos) não se encontre vazia.
Cap. II – Descrição Técnica
42
A variável outrosMedicamentos deve receber uma string de carateres (100 no
máximo) e vai guardar os nomes de outros medicamentos que possam ter o mesmo
princípio ativo.
A variável laboratorio deve receber uma string de carateres (50 no máximo) e vai
guardar o nome do laboratório que produziu o medicamento. Esta variável é
importante para satisfazer o critério de agrupar os medicamentos por laboratório ao
futuramente permitir fazer pesquisas agrupadas por nome de laboratório.
A variável composicao deve receber uma string de carateres (50 no máximo) e
vai guardar a fórmula do medicamento caso seja conhecida.
A variável posologia deve receber uma string de carateres (50 no máximo) e vai
guardar a quantidade diária recomendada quando se utiliza o medicamento.
A variável indicacoes deve receber uma string de carateres (50 no máximo) e vai
guardar as aplicações conhecidas para o uso do medicamento caso sejam conhecidas.
A variável contraIndicacoes deve receber uma string de carateres (50 no
máximo) e vai guardar os efeitos indesejáveis conhecidos do medicamento caso estes
sejam conhecidos.
A variável anterior do tipo apontador para a estrutura Med, será o apontador
para o endereço de memória do registo anterior na lista duplamente ligada.
A variável seguinte do tipo apontador para a estrutura Med, será o apontador
para o endereço de memória do registo seguinte na lista duplamente ligada.
A variável numero deve receber um inteiro e guarda a identificação numérica do
princípio ativo inserido. A inserção deste código será limitada entre 1 e 999 por opção
e tal como na estrutura anterior não poderão ser introduzidos códigos repetidos.
A variável designacao deve receber uma string de carateres (50 no máximo) e vai
guardar o nome do princípio ativo inserido no sistema. Estes princípios podem ser já
ou não existentes na estrutura Med, pois as duas estruturas são independentes.
A variável descricao deve receber uma string de carateres (100 no máximo) e vai
guardar uma breve descrição sobre o princípio ativo. Esta descrição deve ser a mais
Cap. II – Descrição Técnica
43
breve e esclarecedora possível, uma vez que aparecerá no menu de seleção quando se
introduz um novo medicamento.
A variável ant do tipo apontador para a estrutura Principios, será o apontador
para o endereço de memória do registo anterior na lista duplamente ligada.
A variável seg do tipo apontador para a estrutura Principios, será o apontador
para o endereço de memória do registo seguinte na lista duplamente ligada.
2.2 Funções e procedimentos
Para a implementação do programa, foi necessário desenvolver uma série de
funções e procedimentos, tanto para a estrutura Med como para a estrutura
Principios. Apresenta-se um resumo das rotinas desenvolvidas pela ordem que
aparecem no código fonte.
2.2.1 Inserir registo no início da lista ligada (Med)
Este procedimento permite inserir um novo registo no início da lista duplamente
ligada como foi previamente definido, ao mesmo tempo que atualiza os apontadores
da cabeça da lista (início) e da cauda da lista (fim).
2.2.2 Inserir registo no início da lista ligada (Principios)
Este procedimento é similar ao anterior mas para a estrutura dos princípios
ativos. Grande parte das rotinas estará duplicada devido ao uso de duas estruturas
diferentes.
2.2.3 Inserir novo medicamento
Este procedimento permite ao utilizador introduzir dados num novo registo na
estrutura Med. São solicitados os dados ao utilizador, que irão apresentar restrições
de introdução relativamente ao código, e caso a lista ligada Principios não se encontre
vazia o utilizador pode selecionar o princípio ativo de entre um menu que será
apresentado. Após cada inserção, a lista é gravada em ficheiro de texto e é solicitado
ao utilizador se deseja introduzir consecutivamente mais registos.
Cap. II – Descrição Técnica
44
2.2.4 Inserir novo princípio ativo
Este procedimento permite ao utilizador introduzir dados num novo registo da
estrutura Principios. Os dados introduzidos terão restrições relativamente ao número
que terá de ser limitado entre 1 e 999 e não poderá ser repetido. Após cada inserção é
solicitado ao utilizador se pretende introduzir mais registos.
2.2.5 Listar medicamentos
Este procedimento imprime na consola todos os registos presentes na estrutura
Med caso a lista ligada não se encontre vazia.
2.2.6 Listar princípios ativos
Este procedimento imprime na consola todos os registos presentes na estrutura
Principios caso a lista ligada não se encontre vazia.
2.2.7 Gravar estrutura de medicamentos
Este procedimento grava em formato de ficheiro de texto o conteúdo da lista
ligada correspondente à estrutura Med.
2.2.8 Gravar estrutura de princípios ativos
Este procedimento grava em formato de ficheiro de texto o conteúdo da lista
ligada correspondente à estrutura Principios.
2.2.9 Carregar dados de medicamentos
Este procedimento caso tenha um ficheiro de texto válido disponível, carrega os
dados presentes para a lista ligada da estrutura Med através do procedimento inserir
registo no início da lista ligada.
2.2.10 Carregar dados de princípios ativos
Tal como o procedimento anterior, este procedimento carrega os dados
presentes para a lista ligada da estrutura Principios caso exista um ficheiro de texto
válido.
2.2.11 Menu de princípios ativos
Esta função apresenta inicialmente um menu, em que as opções são a listagem
da lista ligada Princípios. Assim, o utilizador deve escolher um dos princípios ativos do
Cap. II – Descrição Técnica
45
menu que será referenciado através do seu número. Após esta escolha ser realizada, a
função retorna o valor dessa escolha.
2.2.12 Pesquisa de princípios ativos
Passando o valor retornado da função anterior por parâmetro a esta função,
consegue-se extrair o nome do princípio ativo que tinha sido selecionado
anteriormente. A função de pesquisa vai assim retornar o nome do princípio ativo
selecionado.
2.2.13 Remover medicamento
Este procedimento permite remover um medicamento através do seu código. Se
não houver medicamentos o procedimento não será executado. No final de cada
remoção é solicitado ao utilizador se deseja continuar e se este for removendo
medicamentos até a lista ligada ficar vazia irá aparecer uma mensagem informando
que não existem mais medicamentos.
2.2.14 Remover princípio ativo
Este procedimento é similar ao anterior, mas funciona para a lista ligada de
princípios ativos.
2.2.15 Pesquisar medicamentos por laboratório
Este procedimento foi criado para satisfazer o critério de agrupar os
medicamentos por laboratórios. É pedido ao utilizador que insira o nome do
laboratório e serão mostrados todos os medicamentos do mesmo laboratório. Caso
não exista o laboratório selecionado será indicado que não existem medicamentos
pertencentes a esse laboratório.
2.2.16 Pesquisa por múltiplos critérios
Este procedimento permite ao utilizador efetuar pesquisas através da conjunção
de dois critérios previamente definidos. Estes critérios podem ser escolhidos pelo
utilizador e caso a conjunção de busca seja verdadeira ele vai mostrar o medicamento
ou medicamentos encontrados. O modo de funcionamento deste procedimento será
explicado mais detalhadamente posteriormente.
Cap. II – Descrição Técnica
46
2.2.17 Alterar dados de medicamento
Este procedimento permite alterar um dado do medicamento previamente
definido pelo utilizador através do seu código. Esta funcionalidade é criada de modo ao
utilizador poder alterar os dados diretamente a partir da aplicação sem ter de recorrer
ao ficheiro de texto.
2.2.18 Alterar dados de princípios ativos
Este procedimento é similar ao anterior, mas funciona para a estrutura
Principios.
2.2.19 Validar código
Esta função permite verificar se o código introduzido na estrutura Med já se
encontra utilizada. Esta função tanto será usada para verificar se o código já existe,
como para impedir que códigos repetidos sejam inseridos.
2.2.20 Validar número
Esta função é muito similar à anterior mas neste caso verifica os números
introduzidos na estrutura Principios.
2.2.21 Validar laboratório
Esta função permite verificar se o laboratório introduzido pelo utilizador existe
dentro da estrutura Med e serve para validar pesquisas que envolvam o nome do
laboratório.
2.2.22 Validar operações com estrutura medicamentos
Esta função é extramente simples, mas ao mesmo tempo importante, pois
permite verificar se a lista ligada Med se encontra ou não vazia dentro de
procedimentos em que a lista ligada não consta na sua assinatura.
2.2.23 Validar operações com estrutura princípios ativos
Esta função é similar à anterior, mas verifica a lista ligada da estrutura Principios.
Cap. II – Descrição Técnica
47
2.2.24 Selecionar critérios
Este procedimento apenas mostra a parte gráfica do menu de opções quando o
utilizador escolhe os critérios para a pesquisa. Foi desenvolvido para manter o código
principal mais pequeno.
2.2.25 Menu alterar medicamentos
Mais uma vez este procedimento apenas mostra a parte gráfica do menu de
opções quando o utilizador escolhe a opção alterar dados de medicamentos. O motivo
da criação deste procedimento foi o mesmo: manter o código principal mais pequeno.
2.2.26 Menu alterar princípios ativos
Este procedimento é muito similar ao anterior mas apresenta os critérios a
alterar para a estrutura Principios.
2.2.27 Inexistência de medicamentos
Este procedimento foi criado para apresentar um cabeçalho que ia ser utilizado
em diversas ocasiões, sempre que não houvesse medicamentos para listar. Para não
estar constantemente a repetir o código foi criado o procedimento.
2.2.28 Inexistência de princípios ativos
Este procedimento é similar ao anterior, mas o cabeçalho é referente à estrutura
Principios, que surge sempre que não há princípios ativos a listar.
2.2.29 Continuar
Este procedimento foi criado para evitar uma repetição excessiva do mesmo
código ao longo do programa. O procedimento faz uma espera, pede ao utilizador que
pressione uma tecla e a seguir limpa a consola.
2.2.30 Navegação nos menus
Estes procedimentos e funções são rigorosamente semelhantes aos utilizados na
primeira aplicação desenvolvida. A diferença comparativamente com esta aplicação é
que aqui estão a ser utilizados três menus encadeados em que é possível navegar
entre eles. Só é possível abandonar a aplicação a partir do primeiro menu devido à
instrução exit selecionando a opção 0.
Cap. II
48
3 Desenvolvimento
Ao se desenvolver o programa, foi garantido que as estruturas de dados eram
independentes e que a sua manipulação não entraria em conflito. A razão de uma
segunda estrutura de dados é carregar diretamente o princípio ativo para a primeira
estrutura, quando a segunda não for vazia. Ao mesmo tempo as duas estruturas
podem ser consultadas e geridas de forma independente.
O resultado final deste programa é o código fonte que se encontra no final do
capítulo. As técnicas de programação foram baseadas na primeira aplicação, sendo
que nesta secção apenas serão demonstradas as inovações desenvolvidas.
3.1 Declarações
Foram declaradas 4 variáveis globais para as listas ligadas do tipo apontador: 2
para a estrutura Med com o endereço inicial nulo e 2 para a estrutura Principios.
Med *aptInicio = NULL;
Med *aptFim = NULL;
Principios *aptInicio2 = NULL;
Principios *aptFim2 = NULL;
Estas declarações permitem manter atualizados os apontadores início e fim da
lista para as duas estruturas sempre que é introduzido um novo registo. Isto é
fundamental para quando se pretender remover um registo em qualquer das listas
ligadas.
3.2 Inserir novo medicamento
No procedimento inserir novo medicamento é declarada uma variável copia do
tipo apontador para carater com endereço inicial nulo.
void inserirMedicamento ()
{
int cod;
char nom[50], pa[50], om[100], lab[50];
char comp[50], pos[50], ind[50], ci[50];
char *copia = NULL;
int chave, manter = 1, teste = 0, teste3 = 0;
char escolha;
Cap. II – Desenvolvimento
49
Este apontador irá receber o endereço de memória do princípio ativo
selecionado, caso a lista ligada Principios não seja vazia quando o procedimento for
executado.
teste3 = validarOperacoesPrincipios (aptInicio2);
if (teste3 == 1)
{
chave = menuPrincipios (aptInicio2);
copia = pesquisaPrincipios (aptInicio2, chave);
strcpy (pa, copia);
}
else
{
printf ("PRINCÍPIO ATIVO: ");
gets (pa);
fflush (stdin);
}
Esta é a parte realmente diferente no programa. Quando o utilizador for inserir o
princípio ativo, é testado se a lista ligada Principios se encontra ou não vazia. Se esta
não estiver vazia é invocada a função menuPrincipios que retorna a escolha do
utilizador para a variável chave.
Seguidamente, através da função pesquisaPrincipios, o endereço de memória do
princípio ativo selecionado é guardado na variável copia.
Finalmente o princípio ativo é copiado para a variável pa através da instrução
strcpy e o programa prossegue.
Caso a lista ligada de princípios esteja vazia é solicitado ao utilizador que
introduza o princípio ativo manualmente.
3.3 Selecionar princípios ativos
A função menuPrincipios lista todos os registos da lista ligada Principios como se
fosse um menu permitindo ao utilizador fazendo uma escolha através do seu número.
No final a função retorna o número selecionado.
Cap. II – Desenvolvimento
50
int menuPrincipios (Principios *aptInicio2)
{
int escolhaNumero = 0;
if (aptInicio2 != NULL)
{
printf ("n");
printf ("*****************************************************n");
printf ("* *n");
printf ("* SELECIONAR PRINCÍPIO ATIVO *n");
printf ("* *n");
printf ("*****************************************************n");
printf ("n");
while (aptInicio2 != NULL)
{
printf ("%d - %s: %sn", aptInicio2 -> numero, aptInicio2 -> designacao,
aptInicio2 -> descricao);
printf ("n");
aptInicio2 = aptInicio2 -> seg;
}
}
printf ("nIntroduzir número: ");
scanf ("%d", &escolhaNumero);
fflush (stdin);
printf ("n");
return (escolhaNumero);
}
3.4 Pesquisa de princípios ativos
A função pesquisaPrincipios percorre a lista ligada Principios enquanto a chave
que recebe por parâmetro for diferente do número de cada um dos seus registos.
Quando encontra uma equivalência se o registo não for nulo retorna a designação do
princípio ativo. Caso contrário retornaria 0, que não irá acontecer neste programa pois
apenas irá pesquisar chaves confirmadas.
char *pesquisaPrincipios (Principios *aptInicio2, int chave)
{
while (aptInicio2 -> numero != chave)
aptInicio2 = aptInicio2 -> seg;
if (aptInicio2 != NULL)
return (aptInicio2 -> designacao);
return (0);
}
Cap. II – Desenvolvimento
51
3.5 Remover medicamentos
Os procedimentos para remover (neste caso remover medicamento) terão dois
testes: um para testar se a operação se justifica, caso contrário é sinal que não existem
medicamentos e outro para verificar se o código de medicamento que se pretende
remover existe.
void remover (Med **endInicio, Med **endFim)
{
Med *aux = *endInicio;
int manter3 = 1, apagar = 0, teste4 = 0, teste5 = 0;
char escolha3;
system ("cls");
teste4 = validarOperacoesMedicamentos (aptInicio);
if (teste4 == -1)
{
naoExiste ();
menu ();
}
else
{
No primeiro caso, se não existirem medicamentos, uma mensagem é impressa e
o programa retorna ao menu de opções. No segundo caso, se o código não existir, é
solicitado ao utilizador se pretende continuar ou retroceder.
while ((aux != NULL) && (aux -> codigo != apagar))
aux = aux -> seguinte;
if ((aux != NULL) && (aux -> anterior == NULL))
{
*endInicio = aux -> seguinte;
free (aux);
}
else if ((aux != NULL) && (aux -> seguinte == NULL))
{
*endFim = aux -> anterior;
aux -> anterior -> seguinte = NULL;
free (aux);
}
else if ((aux!=NULL)&&(aux->seguinte==NULL)&&(aux->anterior==NULL))
{
*endInicio = NULL;
*endFim = NULL;
free (aux);
}
else if (aux != NULL)
{
aux -> anterior -> seguinte = aux -> seguinte;
aux -> seguinte -> anterior = aux -> anterior;
free (aux);
}
Cap. II – Desenvolvimento
52
Se o código for válido, o programa corre a lista ligada enquanto o código a
apagar for diferente do código do registo. Quando aparece uma equivalência existem 4
possibilidades: o registo estar no início da lista ligada (1ª condição), o registo estar no
fim da lista ligada (2ª condição), só existir um registo (3ª condição) ou o registo estar
numa posição algures a meio da lista ligada. Verificada essa condição, são executadas
as instruções para religar a nova lista ligada sem o registo removido e o registo é
apagado através da instrução free.
3.6 Pesquisa por múltiplos critérios
O procedimento pesquisaMultiplos vai permitir efetuar pesquisas pela
conjunção de dois critérios selecionados pelo utilizador.
void pesquisaMultiplos (Med *aptInicio)
{
int criterio1=0, criterio2=0, caminho=0, cnt=0, teste9=0, teste10=0;
teste9 = validarOperacoesMedicamentos (aptInicio);
if (teste9 == -1)
{
naoExiste ();
menu2 ();
}
else
{
selecionarCriterios ();
printf ("nA: ");
scanf ("%d", &criterio1);
fflush (stdin);
printf ("B: ");
scanf ("%d", &criterio2);
fflush (stdin);
caminho = criterio1 * criterio2;
Estes são dados a escolher ao utilizador através da invocação do procedimento
selecionarCriterios. Após isto o utilizador deve introduzir duas escolhas que serão dois
valores de 1 a 4.
printf ("-----------------------------------------------------------n");
printf ("| 1 | Código |n");
printf ("-----------------------------------------------------------n");
printf ("| 2 | Nome |n");
printf ("-----------------------------------------------------------n");
printf ("| 3 | Princípio ativo |n");
printf ("-----------------------------------------------------------n");
printf ("| 4 | Laboratório |n");
printf ("-----------------------------------------------------------n");
Cap. II – Desenvolvimento
53
Existem várias combinações que podem ser simplificadas através de um caminho
de pesquisa. Para isso multiplica-se o valor das duas escolhas:
Código * Nome 2 Nome * Princípio ativo 6
Código * Princípio ativo 3 Nome * Laboratório 8
Código * Laboratório 4 Princípio ativo * Laboratório 12
Como o código por definição é único, qualquer pesquisa envolvendo o código e o
nome, apenas vai encontrar uma ocorrência.
if (caminho == 2) // Pesquisa por código
{
int _cod;
printf ("Código: ");
scanf ("%d", &_cod);
Se o caminho encontrado for 3, a pesquisa será por código e princípio ativo.
else if (caminho == 3) // pesquisa por código/principio
{
int _ccod;
char _ppat[50];
printf ("Código: ");
scanf ("%d", &_ccod);
fflush (stdin);
printf ("Princípio ativo: ");
gets (_ppat);
Se o caminho encontrado for 4, a pesquisa será por código e laboratório.
else if (caminho == 4) // pesquisa por código/laboratório
{
int _codd;
char _labb[50];
printf ("Código: ");
scanf ("%d", &_codd);
fflush (stdin);
printf ("Laboratório: ");
gets (_labb);
Se o caminho encontrado for 6, a pesquisa será por nome e princípio ativo.
else if (caminho == 6) // pesquisa por nome/principio
{
char _nome[50], _pat[50];
printf ("Nome: ");
gets (_nome);
fflush (stdin);
printf ("Princípio ativo: ");
gets (_pat);
Cap. II – Desenvolvimento
54
Se o caminho encontrado for 8, a pesquisa será por nome e laboratório.
else if (caminho == 8) // pesquisa por nome/laboratório
{
char _name[50], _labot[50];
printf ("Nome: ");
gets (_name);
fflush (stdin);
printf ("Laboratório: ");
gets (_labot);
Finalmente, se o caminho encontrado for 12, a pesquisa será por princípio ativo
e laboratório.
else if (caminho == 12) // pesquisa por princípio/laboratório
{
char _pat[50], _laborat[50];
printf ("Princício ativo: ");
gets (_pat);
fflush (stdin);
printf ("Laboratório: ");
gets (_laborat);
3.7 Validar laboratório
As funções de validar operações e validar códigos/números já foram
demonstradas no primeiro trabalho. No entanto esta é a primeira em que a validação é
feita através da instrução strcmp, que é possível realizar através da inclusão da
biblioteca string.h.
int validarLaboratorio (Med *aptInicio, char *test3)
{
while (aptInicio != NULL)
{
if ((strcmp (aptInicio -> laboratorio, test3)) == 0)
return (1);
aptInicio = aptInicio -> seguinte;
}
return (0);
}
A instrução strcmp devolve 0 se ao comparar duas strings elas forem iguais e
devolve 1 se elas forem diferentes. Assim, a lista ligada será percorrida enquanto a
comparação for diferente de 0.
Quando a strcmp devolver 0 significa que encontrou uma equivalência e nesse
caso a função retorna 1. Caso não encontre nenhuma equivalência enquanto houver
registos na lista ligada, a função retorna 0.
Cap. II
55
4 Testes e Resultados
4.1 Menu de opções principal
O menu de opções principal apresenta três funcionalidades fundamentais
(inserir, remover ou alterar medicamento) e capacidade de navegação para outros dois
menus secundários (consultas e gestão de princípios ativos).
Figura 10 – Menu de opções principal.
4.2 Inserir novo medicamento
Esta funcionalidade permite inserir dados de um novo medicamento, escolhendo
neste caso o principio ativo a partir de um menu.
Figura 11 – Inserir novo medicamento.
Cap. II – Testes e Resultados
56
4.3 Alterar dados de medicamentos
Esta funcionalidade permite alterar os dados de um medicamento inserido.
Neste exemplo o código do exame que se pretendia alterar não existia no sistema,
logo é requerido ao utilizador se deseja continuar.
Figura 12 – Alterar dados de medicamentos.
4.4 Pesquisa por laboratório
Esta funcionalidade permite agrupar os medicamentos registados por
laboratório, que é introduzido pelo utilizador. Este é um dos requisitos deste trabalho.
Figura 13 – Pesquisa por laboratório.
Cap. II – Testes e Resultados
57
4.5 Pesquisa por múltiplos critérios
Esta funcionalidade permite pesquisar medicamentos por mais de um critério
selecionados pelo utilizador. Neste caso seria o nome e o laboratório. Este era outro
dos requisitos do trabalho.
Figura 14 – Pesquisa por múltiplos critérios.
4.6 Listar princípios ativos
Esta funcionalidade permite listar os princípios ativos registados na estrutura
auxiliar do sistema. Não é um requisito obrigatório do trabalho.
Figura 15 – Listar princípios ativos.
Cap. II
58
5 Código fonte
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <locale.h>
typedef struct Simposium
{
int codigo;
char nome[50], principioAtivo[50], outrosMedicamentos[100], laboratorio[50];
char composicao[50], posologia[50], indicacoes[50], contraIndicacoes[50];
struct Simposium *anterior;
struct Simposium *seguinte;
}
Med;
typedef struct Generico
{
int numero;
char designacao[50], descricao[100];
struct Generico *ant;
struct Generico *seg;
}
Principios;
Med *aptInicio = NULL;
Med *aptFim = NULL;
Principios *aptInicio2 = NULL;
Principios *aptFim2 = NULL;
void inserir (Med **endInicio, Med **endFim, int cod, char *nom, char *pa,
char *om, char *lab, char *comp, char *pos, char *ind, char *ci);
void inserirPrincipio (Principios **endInicio2, Principios **endFim2, int num,
char *des, char *desc);
void inserirMedicamento ();
void inserirPrincipioAtivo ();
void listar (Med *aptInicio);
void listarPrincipios (Principios *aptInicio2);
void gravar (Med *aptInicio);
void gravarPrincipios (Principios *aptInicio2);
void carregarSimposium ();
void carregarGenerico ();
int menuPrincipios (Principios *aptInicio2);
char *pesquisaPrincipios (Principios *aptInicio2, int chave);
void remover (Med **endInicio, Med **endFim);
void removerPrincipio (Med **endInicio, Med **endFim);
void pesquisaLaboratorio (Med *aptInicio);
void pesquisaMultiplos (Med *aptInicio);
void alterar (Med *aptInicio);
void alterar2 (Principios *aptInicio2);
int validarCodigo (Med *aptInicio, int test);
int validarNumero (Principios *aptInicio2, int test2);
int validarLaboratorio (Med *aptInicio, char *test3);
int validarOperacoesMedicamentos (Med *aptInicio);
int validarOperacoesPrincipios (Principios *aptInicio2);
Cap. II – Código fonte
59
void selecionarCriterios ();
void menuAlterar ();
void menuAlterar2 ();
void naoExiste ();
void naoExiste2 ();
void continuar ();
void capa ();
int fmenu ();
void menu ();
int fmenu2 ();
void menu2 ();
int fmenu3 ();
void menu3 ();
void inserir (Med **endInicio, Med **endFim, int cod, char *nom, char *pa,
char *om, char *lab, char *comp, char *pos, char *ind, char *ci)
{
Med *novo;
novo = (Med*) malloc (sizeof (Med));
novo -> codigo = cod;
strcpy (novo -> nome, nom);
strcpy (novo -> principioAtivo, pa);
strcpy (novo -> outrosMedicamentos, om);
strcpy (novo -> laboratorio, lab);
strcpy (novo -> composicao, comp);
strcpy (novo -> posologia, pos);
strcpy (novo -> indicacoes, ind);
strcpy (novo -> contraIndicacoes, ci);
if (*endInicio == NULL)
{
novo -> seguinte = NULL;
novo -> anterior = NULL;
*endInicio = novo;
*endFim = novo;
}
else
{
(*endInicio) -> anterior = novo;
novo -> seguinte = *endInicio;
novo -> anterior = NULL;
*endInicio = novo;
}
}
void inserirPrincipio (Principios **endInicio2, Principios **endFim2, int num,
char *des, char *desc)
{
Principios *novo2;
novo2 = (Principios*) malloc (sizeof (Principios));
novo2 -> numero = num;
strcpy (novo2 -> designacao, des);
strcpy (novo2 -> descricao, desc);
if (*endInicio2 == NULL)
{
novo2 -> seg = NULL;
novo2 -> ant = NULL;
Cap. II – Código fonte
60
*endInicio2 = novo2;
*endFim2 = novo2;
}
else
{
(*endInicio2) -> ant = novo2;
novo2 -> seg = *endInicio2;
novo2 -> ant = NULL;
*endInicio2 = novo2;
}
}
void inserirMedicamento ()
{
int cod;
char nom[50], pa[50], om[100], lab[50];
char comp[50], pos[50], ind[50], ci[50];
char *copia = NULL;
int chave, manter = 1, teste = 0, teste3 = 0;
char escolha;
system ("cls");
printf ("n");
printf ("*******************************************************n");
printf ("* *n");
printf ("* INSERIR DADOS DO MEDICAMENTO *n");
printf ("* *n");
printf ("*******************************************************n");
printf ("n");
while (manter == 1)
{
printf ("CÓDIGO: ");
scanf ("%d", &cod);
fflush (stdin);
teste = validarCodigo (aptInicio, cod);
if (teste == 1)
{
printf ("nCódigo já se encontra em utilizaçãonn");
manter = 1;
}
else if ((cod < 1) || (cod > 9999))
{
printf ("nIntroduza código entre 1 e 9999nn");
manter = 1;
}
else
manter = 0;
}
printf ("nNOME: ");
gets (nom);
fflush (stdin);
printf ("n");
teste3 = validarOperacoesPrincipios (aptInicio2);
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C
Estruturas de dados dinâmicos em linguagem C

Mais conteúdo relacionado

Mais procurados

1º trabalho base dados
1º trabalho base dados1º trabalho base dados
1º trabalho base dadosessa
 
Sistemas Operacionais - Aula 05 (Concorrência)
Sistemas Operacionais - Aula 05 (Concorrência)Sistemas Operacionais - Aula 05 (Concorrência)
Sistemas Operacionais - Aula 05 (Concorrência)Leinylson Fontinele
 
Introdução à Arquitetura de Computadores
Introdução à Arquitetura de ComputadoresIntrodução à Arquitetura de Computadores
Introdução à Arquitetura de ComputadoresMauro Pereira
 
Arquitetura cliente servidor
Arquitetura cliente servidorArquitetura cliente servidor
Arquitetura cliente servidorMarcia Abrahim
 
Aula1 - Apresentação de Banco de Dados
Aula1 - Apresentação de Banco de DadosAula1 - Apresentação de Banco de Dados
Aula1 - Apresentação de Banco de DadosRafael Albani
 
Aula 10 - Diagrama de Sequencia.pdf
Aula 10 - Diagrama de Sequencia.pdfAula 10 - Diagrama de Sequencia.pdf
Aula 10 - Diagrama de Sequencia.pdfIvanFontainha
 
Sistema Operativo Servidor
Sistema Operativo ServidorSistema Operativo Servidor
Sistema Operativo ServidorDaniel Barros
 
Sistema operativo servidor
Sistema operativo servidorSistema operativo servidor
Sistema operativo servidorSandu Postolachi
 
Apresentação Final de Banco de Dados
Apresentação Final de Banco de DadosApresentação Final de Banco de Dados
Apresentação Final de Banco de Dadossamlobo
 
desafios na implementacao de sistemas distribuidos
desafios na implementacao de sistemas distribuidosdesafios na implementacao de sistemas distribuidos
desafios na implementacao de sistemas distribuidosHélio Jovo
 

Mais procurados (20)

CEF: Modelo OSI
CEF: Modelo OSICEF: Modelo OSI
CEF: Modelo OSI
 
1º trabalho base dados
1º trabalho base dados1º trabalho base dados
1º trabalho base dados
 
Sistemas Operacionais - Aula 05 (Concorrência)
Sistemas Operacionais - Aula 05 (Concorrência)Sistemas Operacionais - Aula 05 (Concorrência)
Sistemas Operacionais - Aula 05 (Concorrência)
 
Manual de portugol
Manual de portugolManual de portugol
Manual de portugol
 
Introdução à Arquitetura de Computadores
Introdução à Arquitetura de ComputadoresIntrodução à Arquitetura de Computadores
Introdução à Arquitetura de Computadores
 
Arquitetura cliente servidor
Arquitetura cliente servidorArquitetura cliente servidor
Arquitetura cliente servidor
 
Tecnologias Atuais de Redes - Aula 3 - VPN [Apostila]
Tecnologias Atuais de Redes - Aula 3 - VPN [Apostila]Tecnologias Atuais de Redes - Aula 3 - VPN [Apostila]
Tecnologias Atuais de Redes - Aula 3 - VPN [Apostila]
 
Projeto de Rede Local (LAN)
Projeto de Rede Local (LAN)Projeto de Rede Local (LAN)
Projeto de Rede Local (LAN)
 
Aula1 - Apresentação de Banco de Dados
Aula1 - Apresentação de Banco de DadosAula1 - Apresentação de Banco de Dados
Aula1 - Apresentação de Banco de Dados
 
Aula 10 - Diagrama de Sequencia.pdf
Aula 10 - Diagrama de Sequencia.pdfAula 10 - Diagrama de Sequencia.pdf
Aula 10 - Diagrama de Sequencia.pdf
 
Sistema Operativo Servidor
Sistema Operativo ServidorSistema Operativo Servidor
Sistema Operativo Servidor
 
Ipv4 e ipv6
Ipv4 e ipv6Ipv4 e ipv6
Ipv4 e ipv6
 
Linguagem SQL
Linguagem SQLLinguagem SQL
Linguagem SQL
 
Sistema operativo servidor
Sistema operativo servidorSistema operativo servidor
Sistema operativo servidor
 
Comunicação de dados
Comunicação de dadosComunicação de dados
Comunicação de dados
 
Apresentação Final de Banco de Dados
Apresentação Final de Banco de DadosApresentação Final de Banco de Dados
Apresentação Final de Banco de Dados
 
desafios na implementacao de sistemas distribuidos
desafios na implementacao de sistemas distribuidosdesafios na implementacao de sistemas distribuidos
desafios na implementacao de sistemas distribuidos
 
Visualg
VisualgVisualg
Visualg
 
Linguagem Dart (Google)
Linguagem Dart (Google)Linguagem Dart (Google)
Linguagem Dart (Google)
 
Endereçamento IPV4
Endereçamento IPV4Endereçamento IPV4
Endereçamento IPV4
 

Semelhante a Estruturas de dados dinâmicos em linguagem C

Programacao cpp
Programacao cppProgramacao cpp
Programacao cppTiago
 
Dissertação Mestrado
Dissertação MestradoDissertação Mestrado
Dissertação MestradoJoel Carvalho
 
Apostila c# iniciantes
Apostila c# iniciantesApostila c# iniciantes
Apostila c# iniciantesCaique Moretto
 
DissertacaoMScValterFinal20070216
DissertacaoMScValterFinal20070216DissertacaoMScValterFinal20070216
DissertacaoMScValterFinal20070216Valter Inacio Jr.
 
Dissertação de Mestrado - Planejamento para Serviços Web Semânticos
Dissertação de Mestrado - Planejamento para Serviços Web SemânticosDissertação de Mestrado - Planejamento para Serviços Web Semânticos
Dissertação de Mestrado - Planejamento para Serviços Web SemânticosJuliana Chahoud
 
Livro - Projeto, Desempenho e Aplicacoes de Sistemas Digitais em FPGAs
Livro - Projeto, Desempenho e Aplicacoes de Sistemas Digitais em FPGAsLivro - Projeto, Desempenho e Aplicacoes de Sistemas Digitais em FPGAs
Livro - Projeto, Desempenho e Aplicacoes de Sistemas Digitais em FPGAsEdward David Moreno
 
My sql
My sqlMy sql
My sqlTiago
 
Sistema Imunológico Artificial para Predição de Fraudes e Furtos de Energia E...
Sistema Imunológico Artificial para Predição de Fraudes e Furtos de Energia E...Sistema Imunológico Artificial para Predição de Fraudes e Furtos de Energia E...
Sistema Imunológico Artificial para Predição de Fraudes e Furtos de Energia E...Mauricio Volkweis Astiazara
 
Relatório tfc caio eduardo silva - implementação de um sistema de aquisição...
Relatório tfc   caio eduardo silva - implementação de um sistema de aquisição...Relatório tfc   caio eduardo silva - implementação de um sistema de aquisição...
Relatório tfc caio eduardo silva - implementação de um sistema de aquisição...Caio Eduardo Silva
 
Certificação Digital : Uma Nova Era de Segurança Eletrônica
Certificação Digital : Uma Nova Era de Segurança EletrônicaCertificação Digital : Uma Nova Era de Segurança Eletrônica
Certificação Digital : Uma Nova Era de Segurança Eletrônicaluizrbs
 
Tcc Bio Cluster
Tcc Bio ClusterTcc Bio Cluster
Tcc Bio ClusterRafael .
 
Intro redes
Intro redesIntro redes
Intro redesTiago
 
Dissertação google inc act on general strike suzart Attain to cpf 051 812 95...
Dissertação  google inc act on general strike suzart Attain to cpf 051 812 95...Dissertação  google inc act on general strike suzart Attain to cpf 051 812 95...
Dissertação google inc act on general strike suzart Attain to cpf 051 812 95...Sandro Santana
 

Semelhante a Estruturas de dados dinâmicos em linguagem C (20)

Sql
SqlSql
Sql
 
Programacao cpp
Programacao cppProgramacao cpp
Programacao cpp
 
Dissertação Mestrado
Dissertação MestradoDissertação Mestrado
Dissertação Mestrado
 
Apostila c# iniciantes
Apostila c# iniciantesApostila c# iniciantes
Apostila c# iniciantes
 
Aspnet mvc
Aspnet mvcAspnet mvc
Aspnet mvc
 
Engenharia De Requisitos
Engenharia De RequisitosEngenharia De Requisitos
Engenharia De Requisitos
 
DissertacaoMScValterFinal20070216
DissertacaoMScValterFinal20070216DissertacaoMScValterFinal20070216
DissertacaoMScValterFinal20070216
 
monografia_andre_paro
monografia_andre_paromonografia_andre_paro
monografia_andre_paro
 
Dissertação de Mestrado - Planejamento para Serviços Web Semânticos
Dissertação de Mestrado - Planejamento para Serviços Web SemânticosDissertação de Mestrado - Planejamento para Serviços Web Semânticos
Dissertação de Mestrado - Planejamento para Serviços Web Semânticos
 
Livro - Projeto, Desempenho e Aplicacoes de Sistemas Digitais em FPGAs
Livro - Projeto, Desempenho e Aplicacoes de Sistemas Digitais em FPGAsLivro - Projeto, Desempenho e Aplicacoes de Sistemas Digitais em FPGAs
Livro - Projeto, Desempenho e Aplicacoes de Sistemas Digitais em FPGAs
 
My sql
My sqlMy sql
My sql
 
Sistema Imunológico Artificial para Predição de Fraudes e Furtos de Energia E...
Sistema Imunológico Artificial para Predição de Fraudes e Furtos de Energia E...Sistema Imunológico Artificial para Predição de Fraudes e Furtos de Energia E...
Sistema Imunológico Artificial para Predição de Fraudes e Furtos de Energia E...
 
Relatório tfc caio eduardo silva - implementação de um sistema de aquisição...
Relatório tfc   caio eduardo silva - implementação de um sistema de aquisição...Relatório tfc   caio eduardo silva - implementação de um sistema de aquisição...
Relatório tfc caio eduardo silva - implementação de um sistema de aquisição...
 
Apostila aspnet mvc
Apostila aspnet mvcApostila aspnet mvc
Apostila aspnet mvc
 
Manualipdoc4 pt
Manualipdoc4 ptManualipdoc4 pt
Manualipdoc4 pt
 
Certificação Digital : Uma Nova Era de Segurança Eletrônica
Certificação Digital : Uma Nova Era de Segurança EletrônicaCertificação Digital : Uma Nova Era de Segurança Eletrônica
Certificação Digital : Uma Nova Era de Segurança Eletrônica
 
Apostilando mysql
Apostilando mysqlApostilando mysql
Apostilando mysql
 
Tcc Bio Cluster
Tcc Bio ClusterTcc Bio Cluster
Tcc Bio Cluster
 
Intro redes
Intro redesIntro redes
Intro redes
 
Dissertação google inc act on general strike suzart Attain to cpf 051 812 95...
Dissertação  google inc act on general strike suzart Attain to cpf 051 812 95...Dissertação  google inc act on general strike suzart Attain to cpf 051 812 95...
Dissertação google inc act on general strike suzart Attain to cpf 051 812 95...
 

Mais de pjclima

Implementação de um robot móvel
Implementação de um robot móvelImplementação de um robot móvel
Implementação de um robot móvelpjclima
 
Desenvolvimento de elevador remoto instrumentado
Desenvolvimento de elevador remoto instrumentadoDesenvolvimento de elevador remoto instrumentado
Desenvolvimento de elevador remoto instrumentadopjclima
 
Sistema de aquisição de um sinal de ECG
Sistema de aquisição de um sinal de ECGSistema de aquisição de um sinal de ECG
Sistema de aquisição de um sinal de ECGpjclima
 
Correção do fator de potência
Correção do fator de potênciaCorreção do fator de potência
Correção do fator de potênciapjclima
 
Desempenho em equipamentos informáticos
Desempenho em equipamentos informáticosDesempenho em equipamentos informáticos
Desempenho em equipamentos informáticospjclima
 
Circuitos retificadores
Circuitos retificadoresCircuitos retificadores
Circuitos retificadorespjclima
 
Interface gráfico para gestão de uma agência de viagens
Interface gráfico para gestão de uma agência de viagensInterface gráfico para gestão de uma agência de viagens
Interface gráfico para gestão de uma agência de viagenspjclima
 
Controlador de ganho automático baseado numa plataforma FPGA
Controlador de ganho automático baseado numa plataforma FPGAControlador de ganho automático baseado numa plataforma FPGA
Controlador de ganho automático baseado numa plataforma FPGApjclima
 

Mais de pjclima (8)

Implementação de um robot móvel
Implementação de um robot móvelImplementação de um robot móvel
Implementação de um robot móvel
 
Desenvolvimento de elevador remoto instrumentado
Desenvolvimento de elevador remoto instrumentadoDesenvolvimento de elevador remoto instrumentado
Desenvolvimento de elevador remoto instrumentado
 
Sistema de aquisição de um sinal de ECG
Sistema de aquisição de um sinal de ECGSistema de aquisição de um sinal de ECG
Sistema de aquisição de um sinal de ECG
 
Correção do fator de potência
Correção do fator de potênciaCorreção do fator de potência
Correção do fator de potência
 
Desempenho em equipamentos informáticos
Desempenho em equipamentos informáticosDesempenho em equipamentos informáticos
Desempenho em equipamentos informáticos
 
Circuitos retificadores
Circuitos retificadoresCircuitos retificadores
Circuitos retificadores
 
Interface gráfico para gestão de uma agência de viagens
Interface gráfico para gestão de uma agência de viagensInterface gráfico para gestão de uma agência de viagens
Interface gráfico para gestão de uma agência de viagens
 
Controlador de ganho automático baseado numa plataforma FPGA
Controlador de ganho automático baseado numa plataforma FPGAControlador de ganho automático baseado numa plataforma FPGA
Controlador de ganho automático baseado numa plataforma FPGA
 

Último

A EXTENSÃO RURAL NO BRASIL Sociologia e Extensão 1 2014.ppt
A EXTENSÃO RURAL NO BRASIL Sociologia e Extensão 1 2014.pptA EXTENSÃO RURAL NO BRASIL Sociologia e Extensão 1 2014.ppt
A EXTENSÃO RURAL NO BRASIL Sociologia e Extensão 1 2014.pptssuserb964fe
 
A Importância dos EPI's no trabalho e no dia a dia laboral
A Importância dos EPI's no trabalho e no dia a dia laboralA Importância dos EPI's no trabalho e no dia a dia laboral
A Importância dos EPI's no trabalho e no dia a dia laboralFranciscaArrudadaSil
 
Treinamento de NR06 Equipamento de Proteção Individual
Treinamento de NR06 Equipamento de Proteção IndividualTreinamento de NR06 Equipamento de Proteção Individual
Treinamento de NR06 Equipamento de Proteção Individualpablocastilho3
 
Tecnólogo em Mecatrônica - Universidade Anhanguera
Tecnólogo em Mecatrônica - Universidade AnhangueraTecnólogo em Mecatrônica - Universidade Anhanguera
Tecnólogo em Mecatrônica - Universidade AnhangueraGuilhermeLucio9
 
Livro Vibrações Mecânicas - Rao Singiresu - 4ª Ed.pdf
Livro Vibrações Mecânicas - Rao Singiresu - 4ª Ed.pdfLivro Vibrações Mecânicas - Rao Singiresu - 4ª Ed.pdf
Livro Vibrações Mecânicas - Rao Singiresu - 4ª Ed.pdfSamuel Ramos
 
Eletricista instalador - Senai Almirante Tamandaré
Eletricista instalador - Senai Almirante TamandaréEletricista instalador - Senai Almirante Tamandaré
Eletricista instalador - Senai Almirante TamandaréGuilhermeLucio9
 
LEAN SIX SIGMA - Garantia da qualidade e segurança
LEAN SIX SIGMA - Garantia da qualidade e segurançaLEAN SIX SIGMA - Garantia da qualidade e segurança
LEAN SIX SIGMA - Garantia da qualidade e segurançaGuilhermeLucio9
 

Último (7)

A EXTENSÃO RURAL NO BRASIL Sociologia e Extensão 1 2014.ppt
A EXTENSÃO RURAL NO BRASIL Sociologia e Extensão 1 2014.pptA EXTENSÃO RURAL NO BRASIL Sociologia e Extensão 1 2014.ppt
A EXTENSÃO RURAL NO BRASIL Sociologia e Extensão 1 2014.ppt
 
A Importância dos EPI's no trabalho e no dia a dia laboral
A Importância dos EPI's no trabalho e no dia a dia laboralA Importância dos EPI's no trabalho e no dia a dia laboral
A Importância dos EPI's no trabalho e no dia a dia laboral
 
Treinamento de NR06 Equipamento de Proteção Individual
Treinamento de NR06 Equipamento de Proteção IndividualTreinamento de NR06 Equipamento de Proteção Individual
Treinamento de NR06 Equipamento de Proteção Individual
 
Tecnólogo em Mecatrônica - Universidade Anhanguera
Tecnólogo em Mecatrônica - Universidade AnhangueraTecnólogo em Mecatrônica - Universidade Anhanguera
Tecnólogo em Mecatrônica - Universidade Anhanguera
 
Livro Vibrações Mecânicas - Rao Singiresu - 4ª Ed.pdf
Livro Vibrações Mecânicas - Rao Singiresu - 4ª Ed.pdfLivro Vibrações Mecânicas - Rao Singiresu - 4ª Ed.pdf
Livro Vibrações Mecânicas - Rao Singiresu - 4ª Ed.pdf
 
Eletricista instalador - Senai Almirante Tamandaré
Eletricista instalador - Senai Almirante TamandaréEletricista instalador - Senai Almirante Tamandaré
Eletricista instalador - Senai Almirante Tamandaré
 
LEAN SIX SIGMA - Garantia da qualidade e segurança
LEAN SIX SIGMA - Garantia da qualidade e segurançaLEAN SIX SIGMA - Garantia da qualidade e segurança
LEAN SIX SIGMA - Garantia da qualidade e segurança
 

Estruturas de dados dinâmicos em linguagem C

  • 1. Instituto Politécnico do Cávado e do Ave Escola Superior de Tecnologia Engenharia Eletrotécnica e de Computadores Estruturas de dados dinâmicos em linguagem C Paulo Lima Junho de 2013
  • 2. ii Resumo Este trabalho, teve como objetivo o desenvolvimento de aplicações em linguagem C, utilizando estruturas de dados dinâmicas. O trabalho foi dividido em três partes, que correspondentes a diferentes aplicações a desenvolver: gestão de um arquivo de exames de diagnóstico médico, gestão de um simposium de medicamentos genéricos e gestão de uma prova desportiva. Em cada aplicação desenvolvida, foi aplicado um tipo de estrutura de dados, sendo o objetivo utilizar listas ligadas simples, listas duplamente ligadas e finalmente as árvores binárias de procura. Foram analisados os problemas propostos, estruturados os dados, desenvolvidas as funções e procedimentos de modo a criar as aplicações e no final aplicaram-se testes ao sistema de modo a precaver possíveis erros. Todas as aplicações foram construídas de modo a evitar situações problemáticas para o utilizador e foram inseridos mecanismos de proteção na inserção de dados de modo a evitar bugs e possíveis situações de conflito do sistema. Palavras-Chave (Tema): Estruturas de dados, Listas ligadas simples, Listas duplamente ligadas, Árvores binárias de procura. Palavras-Chave (Tecnologias): Visual Studio, Linguagem C. “Andar sobre as águas e fazer software a partir de uma especificação, é simples se ambas estiverem congeladas.” Edward V. Berard
  • 3. iii Índice Resumo..............................................................................................................................ii Índice ................................................................................................................................iii Introdução ........................................................................................................................ 1 1 Linguagem C ............................................................................................................. 2 2 Estruturas de dados.................................................................................................. 3 2.1 Listas ligadas simples ......................................................................................... 3 2.2 Listas duplamente ligadas.................................................................................. 4 2.3 Árvores binárias de procura............................................................................... 5 Capítulo I........................................................................................................................... 6 1 Contexto ................................................................................................................... 7 2 Descrição Técnica ..................................................................................................... 8 2.1 Variáveis............................................................................................................. 8 2.2 Funções e procedimentos.................................................................................. 9 2.2.1 Inserir registo no início da lista ligada........................................................ 9 2.2.2 Inserir registo no fim da lista ligada ........................................................... 9 2.2.3 Introduzir dados num registo pelo utilizador........................................... 10 2.2.4 Listar registos da lista ligada..................................................................... 10 2.2.5 Gravar lista ligada em ficheiro de texto ................................................... 10 2.2.6 Carregar lista ligada do ficheiro de texto ................................................. 10 2.2.7 Pesquisar exame por paciente ................................................................. 10 2.2.8 Pesquisar exames por período de tempo ................................................ 10 2.2.9 Alterar dados de um exame ..................................................................... 11 2.2.10 Validar um código de exame .................................................................... 11
  • 4. iv 2.2.11 Validar operações com a lista ligada ........................................................ 11 2.2.12 Apresentar primeira página...................................................................... 11 2.2.13 Apresentar menu...................................................................................... 11 2.2.14 Correr o menu .......................................................................................... 11 3 Desenvolvimento.................................................................................................... 12 3.1 Bibliotecas........................................................................................................ 12 3.2 Declarações...................................................................................................... 12 3.3 Métodos de inserção de dados........................................................................ 13 3.4 Restrições......................................................................................................... 14 3.5 Listar exames ................................................................................................... 15 3.6 Gravar exames ................................................................................................. 15 3.7 Carregar exames .............................................................................................. 16 3.8 Pesquisa de exames por paciente.................................................................... 16 3.9 Pesquisa de exames por data .......................................................................... 17 3.10 Alterar exames................................................................................................. 18 3.11 Validar código .................................................................................................. 19 3.12 Validar operação.............................................................................................. 20 3.13 Função main..................................................................................................... 20 4 Testes e Resultados ................................................................................................ 21 4.1 Página inicial .................................................................................................... 21 4.2 Menu................................................................................................................ 21 4.3 Listar todos os exames..................................................................................... 22 4.4 Pesquisa por paciente...................................................................................... 22 4.5 Pesquisa por data............................................................................................. 23 4.6 Inserir novo exame .......................................................................................... 23
  • 5. v 5 Código fonte ........................................................................................................... 24 Capítulo II........................................................................................................................ 39 1 Contexto ................................................................................................................. 40 2 Descrição Técnica ................................................................................................... 41 2.1 Variáveis........................................................................................................... 41 2.2 Funções e procedimentos................................................................................ 43 2.2.1 Inserir registo no início da lista ligada (Med) ........................................... 43 2.2.2 Inserir registo no início da lista ligada (Principios)................................... 43 2.2.3 Inserir novo medicamento ....................................................................... 43 2.2.4 Inserir novo princípio ativo....................................................................... 44 2.2.5 Listar medicamentos ................................................................................ 44 2.2.6 Listar princípios ativos.............................................................................. 44 2.2.7 Gravar estrutura de medicamentos ......................................................... 44 2.2.8 Gravar estrutura de princípios ativos....................................................... 44 2.2.9 Carregar dados de medicamentos ........................................................... 44 2.2.10 Carregar dados de princípios ativos ......................................................... 44 2.2.11 Menu de princípios ativos ........................................................................ 44 2.2.12 Pesquisa de princípios ativos.................................................................... 45 2.2.13 Remover medicamento............................................................................ 45 2.2.14 Remover princípio ativo ........................................................................... 45 2.2.15 Pesquisar medicamentos por laboratório................................................ 45 2.2.16 Pesquisa por múltiplos critérios ............................................................... 45 2.2.17 Alterar dados de medicamento................................................................ 46 2.2.18 Alterar dados de princípios ativos............................................................ 46 2.2.19 Validar código........................................................................................... 46
  • 6. vi 2.2.20 Validar número......................................................................................... 46 2.2.21 Validar laboratório.................................................................................... 46 2.2.22 Validar operações com estrutura medicamentos.................................... 46 2.2.23 Validar operações com estrutura princípios ativos.................................. 46 2.2.24 Selecionar critérios................................................................................... 47 2.2.25 Menu alterar medicamentos.................................................................... 47 2.2.26 Menu alterar princípios ativos.................................................................. 47 2.2.27 Inexistência de medicamentos................................................................. 47 2.2.28 Inexistência de princípios ativos............................................................... 47 2.2.29 Continuar.................................................................................................. 47 2.2.30 Navegação nos menus.............................................................................. 47 3 Desenvolvimento.................................................................................................... 48 3.1 Declarações...................................................................................................... 48 3.2 Inserir novo medicamento............................................................................... 48 3.3 Selecionar princípios ativos ............................................................................. 49 3.4 Pesquisa de princípios ativos........................................................................... 50 3.5 Remover medicamentos.................................................................................. 51 3.6 Pesquisa por múltiplos critérios ...................................................................... 52 3.7 Validar laboratório........................................................................................... 54 4 Testes e Resultados ................................................................................................ 55 4.1 Menu de opções principal ............................................................................... 55 4.2 Inserir novo medicamento............................................................................... 55 4.3 Alterar dados de medicamentos ..................................................................... 56 4.4 Pesquisa por laboratório.................................................................................. 56 4.5 Pesquisa por múltiplos critérios ...................................................................... 57
  • 7. vii 4.6 Listar princípios ativos ..................................................................................... 57 5 Código fonte ........................................................................................................... 58 Capítulo III....................................................................................................................... 88 1 Contexto ................................................................................................................. 89 2 Descrição Técnica ................................................................................................... 90 2.1 Variáveis........................................................................................................... 90 2.2 Funções e procedimentos................................................................................ 92 2.2.1 Inserir atleta ............................................................................................. 92 2.2.2 Inserir tempos........................................................................................... 92 2.2.3 Introduzir dados do atleta........................................................................ 92 2.2.4 Gravar dados da estrutura (Atletas)......................................................... 92 2.2.5 Carregar dados para a estrutura (Atletas)................................................ 93 2.2.6 Carregar dados para a estrutura (ListaTempos)....................................... 93 2.2.7 Listar atletas inscritos............................................................................... 93 2.2.8 Consultar atletas por número .................................................................. 93 2.2.9 Consultar atletas por percurso................................................................. 93 2.2.10 Listar atletas por tempo de prova............................................................ 94 2.2.11 Listar atletas que terminaram a prova..................................................... 94 2.2.12 Validar número......................................................................................... 94 2.2.13 Validar operação....................................................................................... 94 2.2.14 Navegação nos menus e apresentação.................................................... 94 3 Desenvolvimento.................................................................................................... 95 3.1 Declarações...................................................................................................... 95 3.2 Introduzir atleta............................................................................................... 95 3.3 Carregar dados................................................................................................. 96
  • 8. viii 3.4 Listar atletas..................................................................................................... 97 3.5 Validar número ................................................................................................ 97 3.6 Validar percurso............................................................................................... 97 3.7 Outros .............................................................................................................. 98 4 Testes e Resultados ................................................................................................ 99 4.1 Menu de opções .............................................................................................. 99 4.2 Inserir novo atleta............................................................................................ 99 4.3 Listar atletas inscritos .................................................................................... 100 4.4 Consultar atleta por número ......................................................................... 100 4.5 Consultar atleta por percurso........................................................................ 101 4.6 Listar atletas que terminaram a prova .......................................................... 101 5 Código fonte ......................................................................................................... 102 Conclusões.................................................................................................................... 117 Referências Bibliográficas............................................................................................. 118
  • 9. 1 Introdução As linguagens de programação são uma forma de enviar instruções para um computador ou processador, usando métodos padronizados. Quando um programa de computador é criado, são usadas todo um conjunto de regras sintáticas e semânticas que são caraterísticas da linguagem de programação previamente selecionada para essa aplicação. Essas regras permitem ao programador definir quais os dados onde o computador vai atuar, como serão armazenados esses mesmos dados e todas as ações que o sistema deve tomar conforme as circunstâncias o exigirem. A um conjunto de regras sintáticas e semânticas designa-se de algoritmo. O conjunto das palavras compostos de acordo com as regras referidas anteriormente, designa-se de código fonte. Para um Software poder ser executado, esse código fonte necessita ser traduzido para código máquina (binário) e posteriormente executado pelo processador. A principal vantagem do uso de linguagens de programação é o aumento de produtividade para o programador, uma vez que lhe permite utilizar linguagens de alto nível. Os processadores apenas trabalham com código máquina e se as aplicações tivessem de ser desenvolvidas a este nível, os processos seriam demasiado morosos e em alguns casos praticamente impossíveis de realizar. Ao utilizarem-se linguagens de muito baixo nível também se torna extremamente complicado detetar os erros nos algoritmos de implementação, devido à extrema complexidade dos códigos associados. Utilizando a linguagem de alto nível, para além de se acelerar o processo de criação de algoritmos porque a forma assemelha-se à linguagem humana, facilmente se deteta os erros de implementação nos algoritmos com ajuda do compilador que transforma o código fonte em código máquina antes do processamento.
  • 10. Introdução 2 1 Linguagem C Uma das linguagens de programação mais utilizadas no mundo é a linguagem C. Existem, outras ainda utilizadas atualmente tais como o Pascal, Fortran e Cobol. No entanto será focada a linguagem C que é a linguagem de desenvolvimento deste trabalho prático. A linguagem C foi desenvolvida inicialmente entre 1969 e 1973 no AT&T Bell Lab por Dennis Ritchie e Ken Thompson para a implementação do sistema UNIX (que era originalmente escrito em Assembly). A partir de 1973 com a adição do tipo de dados struct à linguagem C, esta tornou-se suficientemente poderosa para a maioria dos núcleos do UNIX poderem ser escritos em C. Assim, este foi um dos primeiros três sistemas a não serem implementados em linguagem Assembly, abrindo as portas à linguagem C como linguagem de programação preferencial. Ao longo dos anos, a linguagem C foi sofrendo várias adaptações e melhorias, sendo que atualmente se pode definir como uma linguagem de programação de alto nível, compilada, estruturada, imperativa, procedural e padronizada. As suas características mais importantes são: Linguagem extremamente simples. Bibliotecas de rotinas padronizadas, tais como funções matemáticas ou manipulação de strings. Paradigma de programação procedural. Linguagem de pré-processamento que permite compilar vários ficheiros de código fonte. Uso de apontadores flexibiliza a linguagem. Permite a inclusão de código Assembly no programa escrito em C. O uso de estruturas (structs) permite que dados relacionados possam ser manipulados como um todo. Os tipos de dados da linguagem C podem ser do tipo inteiro (com ou sem sinal), reais, carateres, estruturas e ainda muito importante do tipo apontadores.
  • 11. Introdução 3 Os apontadores são um tipo de variável que guarda o endereço de memória de outra variável. Na linguagem C, os apontadores possuem um valor reservado designado NULL que significa que estes não estão a guardar no momento nenhum endereço. Os dados do tipo inteiro (int) servem para guardar números inteiros de valor finito. Podem ser com ou sem sinal e o máximo e mínimo valor que se pode inserir é limitado pela capacidade do processador de execução. Os dados do tipo carater (char) ocupam 1 byte em memória independentemente do sistema operativo e podem guardar carateres ou números inteiros. Através de vetores de carateres é possível criar strings que são cadeias de carateres. Os dados do tipo real (float) servem para guardar números de vírgula flutuante. Estes dados podem ser ainda do tipo double float que apresentam o dobro da capacidade de armazenamento. 2 Estruturas de dados Na linguagem C são largamente usadas estruturas, que são grupos de variáveis organizadas pelo programador e definidas através da criação de um novo tipo de variável pela palavra reservada typedef. Quando se desenvolve uma aplicação em qualquer linguagem de programação é necessário desenvolver uma estrutura de dados que solucione o problema que se pretende resolver. Uma estrutura de dados é uma forma de armazenar e organizar os dados de modo a que estes possam ser utilizados o mais eficazmente possível. O tipo de estrutura selecionada pode depender da aplicação pretendida, sendo que as estruturas mais comuns são as listas ligadas, as árvores binárias de procura, grafos, etc. 2.1 Listas ligadas simples Uma lista ligada simples (LLS) é uma estrutura de dados dinâmicos, composta de células que apontam para o próximo elemento da lista. Para criar uma lista ligada é necessário saber o endereço do seu primeiro elemento, sendo que o ultimo elemento
  • 12. Introdução 4 terá endereço NULL. A figura seguinte representa o esquema das ligações necessárias para desenvolver uma lista ligada simples. Figura 1 – Esquema de uma LLS. Vantagens das LLS: A inserção ou remoção de um elemento da lista ligada não implica mudar outros elementos de lugar. Quando se cria a lista, não é necessário definir o número máximo de elementos que esta poderá ter, pois a memória pode ser alocada dinamicamente. Desvantagens das LLS: Manipular a lista ligada pode ser perigoso, pois se a ligação entre os elementos estiver mal feita, toda a lista ligada pode ser perdida. Para aceder a um elemento nas posições finais da lista, é necessário percorrer todas as posições iniciais. 2.2 Listas duplamente ligadas Uma lista duplamente ligada (LDL) é uma derivação da lista ligada simples. O que diferencia a lista duplamente ligada da lista ligada simples é que a lista duplamente ligada apresenta dois apontadores, um para o endereço de memória do próximo elemento da cadeia e outro apontador para o elemento anterior da cadeia. Como foi visto anteriormente, na lista ligada simples apenas existe um apontador para o endereço de memória do próximo elemento da cadeia. A figura seguinte representa o esquema das ligações necessárias para desenvolver uma lista duplamente ligada.
  • 13. Introdução 5 Figura 2 – Esquema de uma LDL. Vantagens das LDL: Maior controlo dos dados presentes na lista ligada. Existe menor risco de perda acidental dos dados. Desvantagens das LDL: Maior complexidade dos algoritmos. Necessita de mais apontadores. 2.3 Árvores binárias de procura Uma árvore binária de procura (ABP) é uma estrutura de dados que se baseada em nós. Esta estrutura deve respeitar duas regras: os nós da subárvore esquerda devem possuir uma chave com valor inferior ao nó raiz e todos os nós da subárvore direita devem possuir uma chave com valor superior ao nó raiz. As árvores binárias de procura possuem alguma terminologia associada que convém salientar: Nós: representam os registos guardados na árvore. Raiz: é o nó que fica no topo da árvore. Filhos: são os nós que precedem os nós anteriores. Pais: são os nós que antecedem os outros nós. Folhas: são os nós terminais que não possuem ligação com outro nó. Figura 3 – Esquema de uma ABP.
  • 14. 6 Capítulo I Listas ligadas simples Gestão de um arquivo de exames de diagnóstico médico
  • 15. Cap. I 7 1 Contexto Uma clínica médica, ao dispor de múltiplos serviços, departamentos e especialidades, tem a necessidade de gerir todos os exames de diagnóstico que são feitos para cada doente. É necessário arquivar os exames realizados, numa determinada data, por um determinado técnico. Entre outros serviços, é importante: Consultar os exames realizados num determinado período de tempo; Consultar os exames de um determinado doente; Arquivar os exames realizados. Pretende-se o desenvolvimento de uma aplicação em linguagem C, que efetue a gestão desse arquivo de exames, através da utilização de listas ligadas simples. A solução desenvolvida deverá possuir uma componente de interação com o utilizador, bem como a capacidade de armazenar e carregar toda a informação através de ficheiros.
  • 16. Cap. I 8 2 Descrição Técnica Para desenvolver o problema proposto, foi utilizada uma estrutura de dados baseada numa lista ligada simples com nove variáveis para definir o registo Exames e uma variável do tipo apontador para definir o endereço do registo seguinte na lista ligada: typedef struct Arquivo { int codigo, dia, mes, ano, identificacao; char departamento[50], paciente[50], tecnico[50], resultados[100]; struct Arquivo *seguinte; } Exames; 2.1 Variáveis A variável codigo deve receber um inteiro e guarda a identificação numérica do exame inserido. A inserção deste código será limitada entre 1 e 9999 por opção. O programa foi escrito de modo a inserir os registos no início da lista ligada. Assim o utilizador deve tentar manter este código o mais ordenado possível, não fazendo saltos entre valores de inserção. Através de restrições ao nível do código desenvolvido, não será possível a introdução de códigos repetidos. A variável departamento deve receber uma string de carateres (50 no máximo) e vai descrever o exame ao dizer a que departamento pertence. Não foi considerado relevante adicionar mais uma variável com o nome do exame realizado. A variável paciente deve receber uma string de carateres (50 no máximo) e vai guardar o nome do paciente que realizou o exame. A variável identificacao deve receber um inteiro, e guarda o número do paciente que realizou o exame. Este número pode ser um qualquer, sendo que foi pensado inicialmente um conjunto de 9 algarismos referentes ao número do cartão de cidadão. Será através deste número que serão efetuadas as pesquisas por paciente, como tal, este número deverá ser o mais individualizado possível e o operador não deverá utilizar o mesmo número em mais de um paciente.
  • 17. Cap. I – Descrição Técnica 9 A variável tecnico deve receber uma string de carateres (50 no máximo) e vai guardar o nome do funcionário que realizou o exame. As variáveis dia, mes e ano devem receber inteiros e em conjunto vão guardar a data de realização do exame. Estas variáveis terão restrições de inserção, para o utilizador por engano não inserir dias ou meses incoerentes. Por opção, a inserção do ano também foi limitada. Só serão considerados exames realizados a partir do ano 2000 e só será possível inserir até ao ano 2099, altura que o programa estará obviamente obsoleto. A variável resultados deve receber uma string de carateres (100 no máximo) e vai guardar os resultados do paciente no exame realizado. Finalmente a variável seguinte do tipo apontador para a estrutura Exames, será o apontador para o endereço de memória do registo seguinte na lista ligada. 2.2 Funções e procedimentos Para a implementação do programa, foi necessário desenvolver uma série de funções e procedimentos. De seguida apresenta-se um pequeno resumo das rotinas desenvolvidas pela ordem em que aparecem no código fonte. 2.2.1 Inserir registo no início da lista ligada Convencionou-se que o último exame inserido devia ficar no topo da lista. Assim optou-se pelo método de inserir no início da lista ligada. No entanto, quando se carrega o ficheiro de texto, usando este método, os números dos registos acabariam por ficar baralhados, como se vai explicar mais à frente. Assim é também utilizado o inserir no fim da lista ligada mas somente após o carregar do ficheiro de texto. Este método é usado quando os dados são inseridos manualmente pelo utilizador. 2.2.2 Inserir registo no fim da lista ligada Como referido anteriormente, este método é utilizado após serem carregados os dados do ficheiro de texto, de modo a ser mantida a ordem numérica (código) dos registos. Caso fosse utilizado a opção inserir no final da lista ligada, não havia esta necessidade como se vai explicar mais à frente. Assim esta função é complementar e é chamada numa altura diferente da anterior.
  • 18. Cap. I – Descrição Técnica 10 2.2.3 Introduzir dados num registo pelo utilizador Este é um dos procedimentos principais do programa e permite que o utilizador introduza novos registos na lista ligada. Além de pedir os dados a inserir ao utilizador, possui limitações de introdução de dados e invoca outras funções e procedimentos para permitir inserir na lista ligada e gravar. 2.2.4 Listar registos da lista ligada Este procedimento a qualquer altura, percorre a lista ligada, uma vez que esta está permanentemente atualizada, quer seja com dados inseridos pelo utilizador quer com dados carregados do ficheiro de texto e imprime no monitor o conteúdo dos seus diferentes registos. 2.2.5 Gravar lista ligada em ficheiro de texto Este procedimento grava a lista ligada atualizada em formato de ficheiro de texto sempre que é introduzido mais um registo pelo utilizador. 2.2.6 Carregar lista ligada do ficheiro de texto Esta função é responsável por carregar os dados presentes no ficheiro de texto para a lista ligada ao iniciar o programa. Os dados são inseridos na lista ligada através da função inserir no fim da lista, como referido anteriormente. 2.2.7 Pesquisar exame por paciente Este procedimento percorre a lista ligada, comparando o número de pesquisa ao código dos registos até encontrar uma correspondência. Se esta existir, imprime na consola os dados do registo. Se não encontrar qualquer correspondência devolve mensagem informando que registo não existe no sistema. Este procedimento tal como todos os que dependem de a lista ligada não estar vazia, será complementado com outros procedimentos de controlo que impedirão que o procedimento seja executado caso a lista ligada esteja vazia. 2.2.8 Pesquisar exames por período de tempo Este procedimento é mais complexo e será demonstrado numa fase posterior. Permite devolver os registos num período de tempo estabelecido pelo utilizador e tal
  • 19. Cap. I – Descrição Técnica 11 como o procedimento anterior, caso a lista ligada se encontre vazia não vai ser executado. 2.2.9 Alterar dados de um exame Este procedimento que só será executado caso a lista ligada não se encontre vazia, permite ao utilizador alterar os dados dos registos inseridos na lista ligada diretamente a partir do programa. É pedido ao utilizador que selecione o código do exame a alterar e posteriormente o dado pretendido. 2.2.10 Validar um código de exame Esta função permite verificar se determinado código de exame já existe no sistema. Assim será usada com duas funções: nas pesquisas por código de exame permite rejeitar imediatamente caso ele não exista e controla que se possam inserir códigos repetidos quando se está a criar um novo exame. 2.2.11 Validar operações com a lista ligada Esta função é extremamente simples, mas altamente vantajosa, uma vez que verifica se a lista ligada está vazia e serve como sistema de controlo para não deixar correr outros procedimentos sobre uma lista ligada vazia. 2.2.12 Apresentar primeira página Este é um procedimento simples que é invocado na função main que simplesmente apresenta informações ao utilizador, nomeadamente o nome do programa, alunos que o desenvolveram, o docente e outras informações úteis. 2.2.13 Apresentar menu Esta função apresenta duas funcionalidades. A primeira é dar uma imagem gráfica do menu, bem como as suas opções. A segunda é fazer a escolha da opção do utilizador e retornar esse valor. 2.2.14 Correr o menu Permite navegar por entre as opções do programa. Recebe a opção selecionada a partir da função referenciada anteriormente e possui 5 seleções básicas para além da opção de poder abandonar a aplicação.
  • 20. Cap. I 12 3 Desenvolvimento Para desenvolver o programa e para que este funcione corretamente, foi necessário que todos os procedimentos e funções criados interagissem de forma eficaz, sem erros e evitando situações do tipo “beco sem saída” que ocorrem quando as aplicações bloqueiam ou ficam presas em estados sem retorno. O resultado final é o código fonte que se encontra anexado a este relatório, sendo que nesta seção serão explicadas algumas técnicas implementadas. 3.1 Bibliotecas #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <locale.h> Estas instruções permitem incluir bibliotecas ao programa. Além das necessidades normais de input/output (stdio.h), alocação de memória (stdlib.h), manipulação de strings (string.h) e operações com diferentes tipos de variáveis (ctype.h), foi necessário recorrer à biblioteca locale.h para poder incluir carateres especiais em língua portuguesa, que serão largamente utilizados ao longo do programa. 3.2 Declarações Foi declarada globalmente uma variável ListaLigada do tipo apontador para a estrutura Exames com o endereço inicial nulo. Esta declaração global torna possível o seu uso em qualquer procedimento ou função sem a necessidade de voltar a declarar. E desta forma sempre que uma operação for executada sobre a lista ligada esta estará automaticamente atualizada. Exames *ListaLigada = NULL;
  • 21. Cap. I – Desenvolvimento 13 3.3 Métodos de inserção de dados Foi definido que os dados inseridos deviam ficar no início da lista ligada e que era importante manter ordenados os códigos. Se os dados fossem carregados do ficheiro de texto através duma função inserir no início da lista, ia-se perder essa ordenação. Exames *inserirFim (Exames *apt, int cod, char *dep, char *pac, int id, char *tec, int d, int m, int a, char *res) { Exames *aux = apt; Exames *novo; novo = (Exames*) malloc (sizeof (Exames)); novo -> codigo = cod; strcpy (novo -> departamento, dep); strcpy (novo -> paciente, pac); novo -> identificacao = id; strcpy (novo -> tecnico, tec); novo -> dia = d; novo -> mes = m; novo -> ano = a; strcpy (novo -> resultados, res); novo -> seguinte = NULL; if (apt == NULL) return (novo); else { while (aux -> seguinte != NULL) aux = aux -> seguinte; aux -> seguinte = novo; return (apt); } } Assim foi criada uma função auxiliar de inserir no fim da lista ligada que só é utilizada quando os dados são carregados do ficheiro de texto. De referir que este problema de ordenação não ocorreria caso fosse utilizado sempre o inserir no fim da lista ligada. No entanto não foi essa a opção adotada. O que se pretende evitar nesta situação é: Se o utilizador inserir 3 registos consecutivos: 1000, 1001, 1002… Na lista ligada a ordem ficaria: 1002, 1001, 1000… Ao gravar em ficheiro de texto: 1002, 1001, 1000… Ao carregar usando inserir no início: 1000, 1001, 1002… Se fosse inserido mais um registo: 1004, 1000, 1001, 1002…
  • 22. Cap. I – Desenvolvimento 14 3.4 Restrições Dentro do procedimento inserir exame vão existir algumas restrições como se pode observar. while (manter == 1) { printf ("CÓDIGO DO EXAME: "); scanf ("%d", &cod); fflush (stdin); teste = validarCodigo (ListaLigada, cod); if ((cod < 1) || (cod > 9999)) { manter = 1; printf ("nATENÇÃO! Introduza um código entre 1 e 9999nn"); } else if (teste == 1) { manter = 1; printf ("nATENÇÃO! Código já foi introduzidonn"); } else manter = 0; } Ao inserir o código do exame, o programa entra num ciclo e só sai se forem verificadas as restrições: o código introduzido não ser repetido, não ser inferior a 1, nem superior a 9999. Para verificar se o código já existe é usado o procedimento validarCodigo que aparecerá posteriormente no corpo do programa. while (manter == 1) { printf ("DIA: "); scanf ("%d", &d); fflush (stdin); if ((d < 1) || (d > 31)) { manter = 1; printf ("nATENÇÃO! Introduza um dia entre 1 e 31nn"); } else manter = 0; } Este é outro tipo de restrição encontrada dentro do procedimento inserir exame, que neste caso limita a introdução da variável dia. Mais uma vez o programa entra num ciclo e só sairá se uma opção válida for introduzida que neste caso é um inteiro entre 1 e 31. De notar que a variável que permite manter os ciclos é sempre a mesma, uma vez que saindo destes, ela é reinicializada com o valor 1.
  • 23. Cap. I – Desenvolvimento 15 3.5 Listar exames O procedimento listar exames é extremamente simples. Uma vez que ele já recebe a lista ligada pela definição da sua assinatura, existe uma condição que testa se esta é ou não nula. Se for nula, invoca o procedimento naoExiste que apresenta uma mensagem informando que não existem exames gravados. Se a lista ligada não estiver vazia serão impressos no monitor, o conteúdo de todos os exames. if (apt == NULL) { naoExiste (); menu (); } else { printf ("n"); printf ("*****************************************************n"); printf ("* *n"); printf ("* EXAMES ARQUIVADOS *n"); printf ("* *n"); printf ("*****************************************************n"); 3.6 Gravar exames O procedimento gravar exames, permite a gravação em formato de ficheiro de texto, de todos os dados presentes na lista ligada, impedindo estes de se perderem quando o programa é terminado. void gravar (Exames *apt) { FILE *ficheiro; ficheiro = fopen ("Arquivo.txt", "w+"); if (ficheiro != NULL) { while (apt != NULL) { fprintf (ficheiro, "n%dn", apt -> codigo); fprintf (ficheiro, "%sn", apt -> departamento); fprintf (ficheiro, "%sn", apt -> paciente); fprintf (ficheiro, "%dn", apt -> identificacao); fprintf (ficheiro, "%sn", apt -> tecnico); fprintf (ficheiro, "%dn", apt -> dia); fprintf (ficheiro, "%dn", apt -> mes); fprintf (ficheiro, "%dn", apt -> ano); fprintf (ficheiro, "%s", apt -> resultados); apt = apt -> seguinte; } } fclose (ficheiro); }
  • 24. Cap. I – Desenvolvimento 16 3.7 Carregar exames O procedimento carregar exames, vai permitir inserir os dados presentes no ficheiro de texto na lista ligada, ao iniciar o programa. Se ao for executado o procedimento ele não encontrar nenhum ficheiro de texto compatível, imprimirá uma mensagem por cima do menu de opções durante a primeira utilização informando que não existem exames guardados. void carregar () { FILE *ficheiro; int cod, id, d, m, a; char dep[50], pac[50], tec[50], res[100]; ficheiro = fopen ("Arquivo.txt", "r"); if (ficheiro != NULL) { while (!feof (ficheiro)) { fscanf (ficheiro, "n%dn", &cod); fscanf (ficheiro, " %[^n]", dep); fscanf (ficheiro, " %[^n]", pac); fscanf (ficheiro, "%dn", &id); fscanf (ficheiro, " %[^n]", tec); fscanf (ficheiro, "%dn", &d); fscanf (ficheiro, "%dn", &m); fscanf (ficheiro, "%dn", &a); fscanf (ficheiro, " %[^n]", res); ListaLigada=inserirFim(ListaLigada,cod,dep,pac,id,tec,d,m,a,res); } fclose (ficheiro); } else printf ("nNão foram carregados exames!n"); } 3.8 Pesquisa de exames por paciente O procedimento pesquisar exame por paciente é um dos vários que é controlado através da função validarOperacao. Neste caso não era fundamental recorrer a este método, uma vez que ele recebe a lista ligada na sua assinatura. No entanto, este passou a ser o método de testar se o procedimento devia ser ou não executado, sendo que noutros procedimentos ele é mesmo necessário, uma vez que não recebem a lista ligada na assinatura. Assim, se a função retornar -1 significa que a lista ligada se encontra vazia e o procedimento imprime uma mensagem informando que não existem exames. Se a função retornar 1 executa o procedimento.
  • 25. Cap. I – Desenvolvimento 17 void pesquisaPaciente (Exames *apt) { int chave, teste2 = 1; char escolha2; system ("cls"); teste2 = validarOperacao (ListaLigada); if (teste2 == -1) { naoExiste (); menu (); } else { Continuando no procedimento pesquisar exame por paciente, é solicitado uma chave de pesquisa ao utilizador. Seguidamente o programa vai correr a lista ligada enquanto essa chave for diferente das identificações dos registos. Quando encontrar uma correspondência, se o registo não estiver vazio imprime o seu conteúdo. printf ("Identificação: "); scanf ("%d", &chave); fflush (stdin); while ((apt != NULL) && (apt -> identificacao != chave)) apt = apt -> seguinte; if (apt != NULL) { printf ("nn"); printf ("CÓDIGO DO EXAME: %dn", apt -> codigo); printf ("DEPARTAMENTO: %sn", apt -> departamento); printf ("NOME DO PACIENTE: %sn", apt -> paciente); printf ("IDENTIFICAÇÃO DO PACIENTE: %dn", apt -> identificacao); printf ("TÉCNICO RESPONSÁVEL: %sn", apt -> tecnico); printf ("DATA: %d-%d-%dn", apt -> dia, apt -> mes, apt -> ano); printf ("RESULTADOS: %snn", apt -> resultados); } else printf ("nnEXAME INEXISTENTEnn"); 3.9 Pesquisa de exames por data Na pesquisa por data, pretende-se listar os exames realizados entre determinado período de tempo. void pesquisaData (Exames *apt) { int chaveDiaInf, chaveMesInf, chaveAnoInf, inf; int chaveDiaSup, chaveMesSup, chaveAnoSup, sup; int manter2 = 1, teste3 = 0, cnt = 0; char escolha3;
  • 26. Cap. I – Desenvolvimento 18 A solução encontrada foi limitar esse período através de duas chaves: uma inferior e outra superior. Assim tem de ser definidos os dias, meses e anos tanto da chave inferior como da superior. inf = (chaveAnoInf*365) + (chaveMesInf*31) + chaveDiaInf; sup = (chaveAnoSup*365) + (chaveMesSup*31) + chaveDiaSup; Após o utilizador inserir os dados para completar as chaves, que são compostas por limitações de inserção para garantir que não se inserem datas irreais, o programa vai transformar as datas numa chave. Para a obtenção dessa chave a melhor solução encontrada e que provou estar imune a falhas foi transformar toda a data em número de dias. Para isso multiplica-se o ano por 365, o mês por 31, e a estas duas variáveis soma-se o valor do dia. Assim garante-se que nenhuma chave possa ser repetida. while (apt != NULL) { if (((((apt->ano)*365) + ((apt->mes)*31) + (apt->dia)) >= inf) && ((((apt->ano)*365) + ((apt->mes)*31) + (apt->dia)) <= sup)) { printf ("nn"); printf ("CÓDIGO DO EXAME: %dn", apt -> codigo); printf ("DEPARTAMENTO: %sn", apt -> departamento); printf ("NOME DO PACIENTE: %sn", apt -> paciente); printf ("IDENTIFICAÇÃO DO PACIENTE: %dn", apt -> identificacao); printf ("TÉCNICO RESPONSÁVEL: %sn", apt -> tecnico); printf ("DATA: %d-%d-%dn", apt -> dia, apt -> mes, apt -> ano); printf ("RESULTADOS: %snn", apt -> resultados); cnt = cnt++; } apt = apt -> seguinte; } if (cnt == 0) printf ("nnNÃO EXISTEM EXAMES NESTE PERÍODO DE TEMPOnn"); De seguida, enquanto a lista ligada não chegar ao fim, vai ser comparada a chave de cada registo para ver se fica enquadrada entre as duas chaves criadas. Por cada equivalência encontrada é impresso no monitor o conteúdo do registo. 3.10 Alterar exames O procedimento alterar vai permitir substituir dados nos registos da lista ligada, se esta não for vazia. Este procedimento contém várias das restrições anteriores, não apresentando nada de novo, sendo que a mais importante é que se o código do exame a alterar não
  • 27. Cap. I – Desenvolvimento 19 for validado o utilizador tem duas opções: recomeçar, procurando um código válido ou abandonar o procedimento. void alterar (Exames *apt) { int _cod, _id, _d, _m, _a; char _dep[50], _pac[50], _tec[50], _res[100]; int manter3 = 1, modificar = 0, teste4 = 0, teste5 = 0; char escolha4; teste4 = validarOperacao (ListaLigada); if (teste4 == -1) { naoExiste (); menu (); } else { printf ("*****************************************************n"); printf ("* *n"); printf ("* ALTERAR DADOS DE EXAME *n"); printf ("* *n"); printf ("*****************************************************n"); while (manter3 == 1) { printf ("n"); printf ("Código: "); scanf ("%d", &_cod); fflush (stdin); teste5 = validarCodigo (ListaLigada, _cod); if (teste5 == 0) { printf ("nnCódigo não se encontra registadonn"); printf ("Deseja continuar? [S/N]? "); scanf ("%s", &escolha4); 3.11 Validar código Como já antes referido esta função que é várias vezes invocada, permite verificar se um determinado código já se encontra utilizado na lista ligada. Percorre a lista ligada e se encontrar uma equivalência retorna 1. Caso contrário, retorna 0. int validarCodigo (Exames *apt, int test) { while (apt != NULL) { if (apt -> codigo == test) return (1); apt = apt -> seguinte; } return (0); }
  • 28. Cap. I – Desenvolvimento 20 3.12 Validar operação Este procedimento que é largamente utilizado, testa se a lista ligada é ou não vazia. Se for nula, devolve -1. Caso contrário devolve 1. int validarOperacao (Exames *apt) { if (apt == NULL) return (-1); else return (1); } 3.13 Função main Na função main foi necessário incluir a instrução setlocale configurada para “Portuguese” de modo a permitir a inclusão de carateres especiais em língua portuguesa na escrita. int main (void) { setlocale (LC_ALL,"Portuguese"); capa (); carregar (); menu (); return (0); }
  • 29. Cap. I 21 4 Testes e Resultados 4.1 Página inicial A página inicial apresenta variadas informações, tais como o nome de quem desenvolveu o trabalho, o nome da aplicação, docente e unidade curricular para a qual esta foi desenvolvida. Figura 4 – Página inicial. 4.2 Menu O menu de opções é um dos aspetos mais importantes do programa, uma vez que permite navegar entre as diversas funcionalidades e ao mesmo tempo apresentar um ambiente gráfico agradável ao utilizador. Figura 5 – Menu de opções.
  • 30. Cap. I – Testes e Resultados 22 4.3 Listar todos os exames A opção listar todos os exames, imprime no monitor os dados de todos os exames arquivados, sendo que o último exame inserido aparecerá sempre no topo da lista. É a forma mais rápida de ter acesso aos exames guardados no programa. Figura 6 – Listar todos os exames. 4.4 Pesquisa por paciente A pesquisa por paciente é utilizada quando se pretende procurar um exame associado a um paciente para o qual previamente se conhece o número de identificação. No final de cada pesquisa é solicitado ao utilizador se pretende efetuar uma nova pesquisa. Figura 7 – Pesquisa por paciente.
  • 31. Cap. I – Testes e Resultados 23 4.5 Pesquisa por data A pesquisa por período de tempo permite encontrar exames realizados num determinado período de tempo definido pelo utilizador. Caso não seja encontrado o pretendido, no final é solicitado ao utilizador se deseja continuar. Figura 8 – Pesquisa por período de tempo. 4.6 Inserir novo exame Os dados de um novo exame são inseridos consecutivamente, com a opção de introduzir os dados de vários pacientes. Figura 9 – Inserir novo exame.
  • 32. Cap. I 24 5 Código fonte #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <locale.h> typedef struct Arquivo { int codigo, dia, mes, ano, identificacao; char departamento[50], paciente[50], tecnico[50], resultados[100]; struct Arquivo *seguinte; } Exames; Exames *ListaLigada = NULL; void inserirExame (); void listar (Exames *apt); void gravar (Exames *apt); void carregar (); void pesquisaPaciente (Exames *apt); void pesquisaData (Exames *apt); void alterar (Exames *apt); int validarCodigo (Exames *apt, int test); int validarOperacao (Exames *apt); void menuAlterar (); void naoExiste (); void continuar (); void capa (); int fmenu (); void menu (); Exames *inserirInicio (Exames *apt, int cod, char *dep, char *pac, int id, char *tec, int d, int m, int a, char *res) { Exames *novo; novo = (Exames*) malloc (sizeof (Exames)); novo -> codigo = cod; strcpy (novo -> departamento, dep); strcpy (novo -> paciente, pac); novo -> identificacao = id; strcpy (novo -> tecnico, tec); novo -> dia = d; novo -> mes = m; novo -> ano = a; strcpy (novo -> resultados, res); novo -> seguinte = apt; return (novo); }
  • 33. Cap. I – Código fonte 25 Exames *inserirFim (Exames *apt, int cod, char *dep, char *pac, int id, char *tec, int d, int m, int a, char *res) { Exames *aux = apt; Exames *novo; novo = (Exames*) malloc (sizeof (Exames)); novo -> codigo = cod; strcpy (novo -> departamento, dep); strcpy (novo -> paciente, pac); novo -> identificacao = id; strcpy (novo -> tecnico, tec); novo -> dia = d; novo -> mes = m; novo -> ano = a; strcpy (novo -> resultados, res); novo -> seguinte = NULL; if (apt == NULL) return (novo); else { while (aux -> seguinte != NULL) aux = aux -> seguinte; aux -> seguinte = novo; return (apt); } } void inserirExame () { int cod, id, d, m, a; char dep[50], pac[50], tec[50], res[100]; int manter = 1, teste = 0; char escolha; system ("cls"); printf ("n"); printf ("*******************************************************n"); printf ("* *n"); printf ("* INSERIR DADOS DO EXAME *n"); printf ("* *n"); printf ("*******************************************************n"); printf ("n"); while (manter == 1) { printf ("CÓDIGO DO EXAME: "); scanf ("%d", &cod); fflush (stdin); teste = validarCodigo (ListaLigada, cod); if ((cod < 1) || (cod > 9999)) { manter = 1; printf ("nATENÇÃO! Introduza um código entre 1 e 9999nn"); } else if (teste == 1)
  • 34. Cap. I – Código fonte 26 { manter = 1; printf ("nATENÇÃO! Código já foi introduzidonn"); } else manter = 0; } manter = 1; printf ("nDEPARTAMENTO: "); gets (dep); fflush (stdin); printf ("nNOME DO PACIENTE: "); gets (pac); fflush (stdin); printf ("nIDENTIFICAÇÃO DO PACIENTE: "); scanf ("%d", &id); fflush (stdin); printf ("nTÉCNICO RESPONSÁVEL: "); gets (tec); fflush (stdin); printf ("nDATA DO EXAMEn"); while (manter == 1) { printf ("DIA: "); scanf ("%d", &d); fflush (stdin); if ((d < 1) || (d > 31)) { manter = 1; printf ("nATENÇÃO! Introduza um dia entre 1 e 31nn"); } else manter = 0; } manter = 1; while (manter == 1) { printf ("MÊS: "); scanf ("%d", &m); fflush (stdin); if ((m < 1) || (m > 12)) { manter = 1; printf ("nATENÇÃO! Introduza um mês entre 1 e 12nn"); } else manter = 0; } manter = 1; while (manter == 1) { printf ("ANO: "); scanf ("%d", &a);
  • 35. Cap. I – Código fonte 27 fflush (stdin); if ((a < 2000) || (a > 2099)) { manter = 1; printf ("nATENÇÃO! Introduza um ano entre 2000 e 2099nn"); } else manter = 0; } manter = 1; printf ("nRESULTADOS: "); gets (res); fflush (stdin); ListaLigada = inserirInicio (ListaLigada,cod,dep,pac,id,tec,d,m,a,res); gravar (ListaLigada); printf ("nnDeseja continuar? [S/N] "); scanf ("%s", &escolha); fflush (stdin); if ((escolha == 'S') || (escolha == 's')) { system ("cls"); inserirExame (); } else { system ("cls"); menu (); } } void listar (Exames *apt) { system ("cls"); if (apt == NULL) { naoExiste (); menu (); } else { printf ("n"); printf ("*****************************************************n"); printf ("* *n"); printf ("* EXAMES ARQUIVADOS *n"); printf ("* *n"); printf ("*****************************************************n"); printf ("n"); while (apt != NULL) { printf ("n"); printf ("CÓDIGO DO EXAME: %dn", apt -> codigo); printf ("DEPARTAMENTO: %sn", apt -> departamento);
  • 36. Cap. I – Código fonte 28 printf ("NOME DO PACIENTE: %sn", apt -> paciente); printf ("IDENTIFICAÇÃO DO PACIENTE: %dn", apt -> identificacao); printf ("TÉCNICO RESPONSÁVEL: %sn", apt -> tecnico); printf ("DATA: %d-%d-%dn", apt -> dia, apt -> mes, apt -> ano); printf ("RESULTADOS: %snn", apt -> resultados); apt = apt -> seguinte; } } continuar (); menu (); } void gravar (Exames *apt) { FILE *ficheiro; ficheiro = fopen ("Arquivo.txt", "w+"); if (ficheiro != NULL) { while (apt != NULL) { fprintf (ficheiro, "n%dn", apt -> codigo); fprintf (ficheiro, "%sn", apt -> departamento); fprintf (ficheiro, "%sn", apt -> paciente); fprintf (ficheiro, "%dn", apt -> identificacao); fprintf (ficheiro, "%sn", apt -> tecnico); fprintf (ficheiro, "%dn", apt -> dia); fprintf (ficheiro, "%dn", apt -> mes); fprintf (ficheiro, "%dn", apt -> ano); fprintf (ficheiro, "%s", apt -> resultados); apt = apt -> seguinte; } } fclose (ficheiro); } void carregar () { FILE *ficheiro; int cod, id, d, m, a; char dep[50], pac[50], tec[50], res[100]; ficheiro = fopen ("Arquivo.txt", "r"); if (ficheiro != NULL) { while (!feof (ficheiro)) { fscanf (ficheiro, "n%dn", &cod); fscanf (ficheiro, " %[^n]", dep); fscanf (ficheiro, " %[^n]", pac); fscanf (ficheiro, "%dn", &id); fscanf (ficheiro, " %[^n]", tec); fscanf (ficheiro, "%dn", &d); fscanf (ficheiro, "%dn", &m); fscanf (ficheiro, "%dn", &a); fscanf (ficheiro, " %[^n]", res);
  • 37. Cap. I – Código fonte 29 ListaLigada=inserirFim(ListaLigada,cod,dep,pac,id,tec,d,m,a,res); } fclose (ficheiro); } else printf ("nNão foram carregados exames!n"); } void pesquisaPaciente (Exames *apt) { int chave, teste2 = 1; char escolha2; system ("cls"); teste2 = validarOperacao (ListaLigada); if (teste2 == -1) { naoExiste (); menu (); } else { printf ("n"); printf ("*****************************************************n"); printf ("* *n"); printf ("* PESQUISAR EXAME POR PACIENTE *n"); printf ("* *n"); printf ("*****************************************************n"); printf ("n"); printf ("Identificação: "); scanf ("%d", &chave); fflush (stdin); while ((apt != NULL) && (apt -> identificacao != chave)) apt = apt -> seguinte; if (apt != NULL) { printf ("nn"); printf ("CÓDIGO DO EXAME: %dn", apt -> codigo); printf ("DEPARTAMENTO: %sn", apt -> departamento); printf ("NOME DO PACIENTE: %sn", apt -> paciente); printf ("IDENTIFICAÇÃO DO PACIENTE: %dn", apt -> identificacao); printf ("TÉCNICO RESPONSÁVEL: %sn", apt -> tecnico); printf ("DATA: %d-%d-%dn", apt -> dia, apt -> mes, apt -> ano); printf ("RESULTADOS: %snn", apt -> resultados); } else printf ("nnEXAME INEXISTENTEnn"); printf ("nDeseja efetuar nova pesquisa? [S/N]? "); scanf ("%s", &escolha2); fflush (stdin); if ((escolha2 == 'S') || (escolha2 == 's')) { system ("cls"); pesquisaPaciente (ListaLigada); }
  • 38. Cap. I – Código fonte 30 else { system ("cls"); menu (); } } } void pesquisaData (Exames *apt) { int chaveDiaInf, chaveMesInf, chaveAnoInf, inf; int chaveDiaSup, chaveMesSup, chaveAnoSup, sup; int manter2 = 1, teste3 = 0, cnt = 0; char escolha3; system ("cls"); teste3 = validarOperacao (ListaLigada); if (teste3 == -1) { naoExiste (); menu (); } else { printf ("n"); printf ("*****************************************************n"); printf ("* *n"); printf ("* PESQUISAR EXAMES POR PERÍODO DE TEMPO... *n"); printf ("* *n"); printf ("*****************************************************n"); printf ("n"); printf ("Data Inicialn"); while (manter2 == 1) { printf ("Dia: "); scanf ("%d", &chaveDiaInf); fflush (stdin); if ((chaveDiaInf < 1) || (chaveDiaInf > 31)) { manter2 = 1; printf ("nATENÇÃO! Introduza um dia entre 1 e 31nn"); } else manter2 = 0; } manter2 = 1; while (manter2 == 1) { printf ("Mês: "); scanf ("%d", &chaveMesInf); fflush (stdin); if ((chaveMesInf < 1) || (chaveMesInf > 12)) { manter2 = 1;
  • 39. Cap. I – Código fonte 31 printf ("nATENÇÃO! Introduza um mês entre 1 e 12nn"); } else manter2 = 0; } manter2 = 1; while (manter2 == 1) { printf ("Ano: "); scanf ("%d", &chaveAnoInf); fflush (stdin); if ((chaveAnoInf < 2000) || (chaveAnoInf > 2099)) { manter2 = 1; printf ("nATENÇÃO! Introduza um ano entre 2000 e 2099nn"); } else manter2 = 0; } manter2 = 1; printf ("n"); printf ("Data Finaln"); while (manter2 == 1) { printf ("Dia: "); scanf ("%d", &chaveDiaSup); fflush (stdin); if ((chaveDiaSup < 1) || (chaveDiaSup > 31)) { manter2 = 1; printf ("nATENÇÃO! Introduza um dia entre 1 e 31nn"); } else manter2 = 0; } manter2 = 1; while (manter2 == 1) { printf ("Mês: "); scanf ("%d", &chaveMesSup); fflush (stdin); if ((chaveMesSup < 1) || (chaveMesSup > 12)) { manter2 = 1; printf ("nATENÇÃO! Introduza um mês entre 1 e 12nn"); } else manter2 = 0; } manter2 = 1;
  • 40. Cap. I – Código fonte 32 while (manter2 == 1) { printf ("Ano: "); scanf ("%d", &chaveAnoSup); fflush (stdin); if ((chaveAnoSup < 2000) || (chaveAnoSup > 2099)) { manter2 = 1; printf ("nATENÇÃO! Introduza um ano entre 2000 e 2099nn"); } else manter2 = 0; } manter2 = 1; inf = (chaveAnoInf*365) + (chaveMesInf*31) + chaveDiaInf; sup = (chaveAnoSup*365) + (chaveMesSup*31) + chaveDiaSup; while (apt != NULL) { if (((((apt->ano)*365) + ((apt->mes)*31) + (apt->dia)) >= inf) && ((((apt->ano)*365) + ((apt->mes)*31) + (apt->dia)) <= sup)) { printf ("nn"); printf ("CÓDIGO DO EXAME: %dn", apt -> codigo); printf ("DEPARTAMENTO: %sn", apt -> departamento); printf ("NOME DO PACIENTE: %sn", apt -> paciente); printf ("IDENTIFICAÇÃO DO PACIENTE: %dn", apt -> identificacao); printf ("TÉCNICO RESPONSÁVEL: %sn", apt -> tecnico); printf ("DATA: %d-%d-%dn", apt -> dia, apt -> mes, apt -> ano); printf ("RESULTADOS: %snn", apt -> resultados); cnt = cnt++; } apt = apt -> seguinte; } if (cnt == 0) printf ("nnNÃO EXISTEM EXAMES NESTE PERÍODO DE TEMPOnn"); printf ("nDeseja efetuar nova pesquisa? [S/N]? "); scanf ("%s", &escolha3); fflush (stdin); if ((escolha3 == 'S') || (escolha3 == 's')) { system ("cls"); pesquisaData (ListaLigada); } else { system ("cls"); menu (); } } }
  • 41. Cap. I – Código fonte 33 void alterar (Exames *apt) { int _cod, _id, _d, _m, _a; char _dep[50], _pac[50], _tec[50], _res[100]; int manter3 = 1, modificar = 0, teste4 = 0, teste5 = 0; char escolha4; system ("cls"); teste4 = validarOperacao (ListaLigada); if (teste4 == -1) { naoExiste (); menu (); } else { printf ("n"); printf ("*****************************************************n"); printf ("* *n"); printf ("* ALTERAR DADOS DE EXAME *n"); printf ("* *n"); printf ("*****************************************************n"); while (manter3 == 1) { printf ("n"); printf ("Código: "); scanf ("%d", &_cod); fflush (stdin); teste5 = validarCodigo (ListaLigada, _cod); if (teste5 == 0) { printf ("nnCódigo não se encontra registadonn"); printf ("Deseja continuar? [S/N]? "); scanf ("%s", &escolha4); fflush (stdin); if ((escolha4 == 'S') || (escolha4 == 's')) manter3 = 1; else { system ("cls"); menu (); } } else { manter3 = 0; system ("cls"); } } manter3 = 1; menuAlterar ();
  • 42. Cap. I – Código fonte 34 while (manter3 == 1) { printf ("Selecione opção: "); scanf ("%d", &modificar); fflush (stdin); if ((modificar < 1) || (modificar > 6)) { manter3 = 1; printf ("nIntroduza opção entre 1 e 6nn"); } else manter3 = 0; } while ((apt != NULL) && (apt -> codigo != _cod)) apt = apt -> seguinte; if ((apt != NULL) && (modificar == 1)) { printf ("nNovo departamento: "); gets (_dep); fflush (stdin); strcpy (apt -> departamento, _dep); } else if ((apt != NULL) && (modificar == 2)) { printf ("nNovo paciente: "); gets (_pac); fflush (stdin); strcpy (apt -> paciente, _pac); } else if ((apt != NULL) && (modificar == 3)) { printf ("nNova identificação: "); scanf ("%d", &_id); fflush (stdin); apt -> identificacao = _id; } else if ((apt != NULL) && (modificar == 4)) { printf ("nNovo técnico: "); gets (_tec); fflush (stdin); strcpy (apt -> tecnico, _tec); } else if ((apt != NULL) && (modificar == 5)) { printf ("nNova datan"); printf ("Dia: "); scanf ("%d", &_d); fflush (stdin); printf ("Mês: "); scanf ("%d", &_m); fflush (stdin); printf ("Ano: "); scanf ("%d", &_a); fflush (stdin); apt -> dia = _d; apt -> mes = _m; apt -> ano = _a; }
  • 43. Cap. I – Código fonte 35 else if ((apt != NULL) && (modificar == 6)) { printf ("nNovos resultados: "); gets (_res); fflush (stdin); strcpy (apt -> resultados, _res); } printf ("nnEXAME ALTERADO!n"); gravar (ListaLigada); printf ("nnDeseja efetuar nova alteração? [S/N]? "); scanf ("%s", &escolha4); fflush (stdin); if ((escolha4 == 'S') || (escolha4 == 's')) { system ("cls"); alterar (ListaLigada); } else { system ("cls"); menu (); } } } int validarCodigo (Exames *apt, int test) { while (apt != NULL) { if (apt -> codigo == test) return (1); apt = apt -> seguinte; } return (0); } int validarOperacao (Exames *apt) { if (apt == NULL) return (-1); else return (1); } void menuAlterar () { printf ("n"); printf ("*******************************************************n"); printf ("* *n"); printf ("* ALTERAR DADOS DE EXAME *n"); printf ("* *n"); printf ("*******************************************************n"); printf ("-----------------------------------------------------------n");
  • 44. Cap. I – Código fonte 36 printf ("| 1 | Departamento |n"); printf ("-----------------------------------------------------------n"); printf ("| 2 | Paciente |n"); printf ("-----------------------------------------------------------n"); printf ("| 3 | Identificação do paciente |n"); printf ("-----------------------------------------------------------n"); printf ("| 4 | Técnico responsável |n"); printf ("-----------------------------------------------------------n"); printf ("| 5 | Data do exame |n"); printf ("-----------------------------------------------------------n"); printf ("| 6 | Resultados |n"); printf ("-----------------------------------------------------------n"); printf ("n"); } void naoExiste () { printf ("nn"); printf ("*******************************************************n"); printf ("* *n"); printf ("* NÃO EXISTEM EXAMES ARQUIVADOS *n"); printf ("* *n"); printf ("*******************************************************n"); printf ("n"); printf ("n"); printf ("Prima uma tecla para continuar...n"); getchar (); system ("cls"); } void continuar () { printf ("nPrima uma tecla para continuar...n"); getchar (); system ("cls"); } void capa () { printf ("n"); printf ("-------------------------------------------------------n"); printf ("| |n"); printf ("| TRABALHO PRÁTICO DE PROGRAMAÇÃO I |n"); printf ("| |n"); printf ("| Aplicação A |n"); printf ("| |n"); printf ("-------------------------------------------------------n"); printf ("| |n"); printf ("| ALUNOS: Paulo Lima Nº 6522 |n"); printf ("| |n"); printf ("-------------------------------------------------------n"); printf ("| |n"); printf ("| DOCENTE: João Carlos Silva |n"); printf ("| |n"); printf ("-------------------------------------------------------n"); printf (" n"); printf ("Prima uma tecla para continuar...n"); getchar (); fflush (stdin);
  • 45. Cap. I – Código fonte 37 system ("cls"); } int fmenu () { char op[10]; int manter4 = 1, i = 0, t = 0, opc = 0; while (manter4 == 1) { printf (" nn"); printf ("----------------------------------------------------n"); printf ("| | |n"); printf ("| MENU | SISTEMA DE GESTÃO DE EXAMES MÉDICOS |n"); printf ("| | |n"); printf ("----------------------------------------------------n"); printf ("| 1 | Inserir novo exame |n"); printf ("----------------------------------------------------n"); printf ("| 2 | Consultar exame por paciente |n"); printf ("----------------------------------------------------n"); printf ("| 3 | Consultar exames por período de tempo |n"); printf ("----------------------------------------------------n"); printf ("| 4 | Listar todos os exames |n"); printf ("----------------------------------------------------n"); printf ("| 5 | Alterar dados de exame |n"); printf ("----------------------------------------------------n"); printf ("| 0 | Sair |n"); printf ("----------------------------------------------------n"); printf ("n"); printf ("Seleccionar uma opção: "); fflush (stdin); gets (op); t = strlen (op); for (i = 0; i < t; i++) { if (isdigit (op[i]) != 0) manter4 = 0; else { manter4 = 1; printf ("nATENÇÃO! Introduza um númeron"); getchar (); system ("cls"); } } if (manter4 == 0) { opc = atoi (op); if ((opc!=1) && (opc!=2) && (opc!=3) && (opc!=4) && (opc!=5) && (opc!=0)) { manter4 = 1; printf ("nATENÇÃO! Introduza uma opção entre 0 e 5n"); getchar (); system ("cls"); opc = 0; }
  • 46. Cap. I – Código fonte 38 else manter4 = 0; } } return (opc); } void menu () { int opcao = 0; opcao = fmenu (); while (opcao != 0) { switch (opcao) { case 1: inserirExame (); break; case 2: pesquisaPaciente (ListaLigada); break; case 3: pesquisaData (ListaLigada); break; case 4: listar (ListaLigada); break; case 5: alterar (ListaLigada); break; } } if (opcao == 0) exit (0); } int main (void) { setlocale (LC_ALL,"Portuguese"); capa (); carregar (); menu (); return (0); }
  • 47. 39 Capítulo II Listas duplamente ligadas Gestão de um simposium de medicamentos genéricos
  • 48. Cap. II 40 1 Contexto Uma empresa farmacêutica pretende desenvolver um simpósio de medicamentos genéricos para fornecer a médicos de várias especialidades. Este simpósio deverá conter toda a informação que o médico considere útil e necessária, tais como indicações, contraindicações, posologia, princípio ativo, composição, outros medicamentos com o mesmo princípio ativo, etc. Os medicamentos devem estar agrupados por laboratórios, sendo possível: Registar novo medicamento. Registar novo princípio ativo. Consultar por múltiplos critérios. Remoção de medicamento. Pretende-se o desenvolvimento de uma aplicação em linguagem C, que efetue a gestão desse simpósio, através da utilização de listas duplamente ligadas. A solução desenvolvida deverá possuir uma componente de interação com o utilizador, bem como a capacidade de armazenar e carregar toda a informação através de ficheiros.
  • 49. Cap. II 41 2 Descrição Técnica Para desenvolver esta segunda aplicação proposta e de modo a dar uma solução o mais eficaz possível, foram utilizadas duas estruturas de dados baseadas em listas duplamente ligadas. A primeira estrutura foi denominada de Med e desenvolvida para guardar os dados associados aos medicamentos genéricos. typedef struct Simposium { int codigo; char nome[50], principioAtivo[50], outrosMedicamentos[100], laboratorio[50]; char composicao[50], posologia[50], indicacoes[50], contraIndicacoes[50]; struct Simposium *anterior; struct Simposium *seguinte; } Med; A segunda estrutura foi denominada de Principios e foi desenvolvida com o intuito de guardar os princípios ativos autonomamente, de modo que estes possam sempre que requeridos ser chamados a ser inseridos na estrutura principal. typedef struct Generico { int numero; char designacao[50], descricao[100]; struct Generico *ant; struct Generico *seg; } Principios; 2.1 Variáveis A variável codigo deve receber um inteiro e guarda a identificação numérica do medicamento inserido. A inserção deste código será limitada entre 1 e 9999 por opção e não poderão ser introduzidos códigos repetidos. O programa foi escrito de modo a inserir os registos no início da lista ligada, sendo que para este caso a ordenação não é importante. A variável nome deve receber uma string de carateres (50 no máximo) e vai guardar o nome do medicamento inserido no sistema. A variável principioAtivo deve receber uma string de carateres (50 no máximo) e vai indicar o princípio ativo que está associado ao medicamento. Este princípio ativo pode ser introduzido diretamente pelo utilizador, ou escolhido através de um menu caso a segunda estrutura (Princípios Ativos) não se encontre vazia.
  • 50. Cap. II – Descrição Técnica 42 A variável outrosMedicamentos deve receber uma string de carateres (100 no máximo) e vai guardar os nomes de outros medicamentos que possam ter o mesmo princípio ativo. A variável laboratorio deve receber uma string de carateres (50 no máximo) e vai guardar o nome do laboratório que produziu o medicamento. Esta variável é importante para satisfazer o critério de agrupar os medicamentos por laboratório ao futuramente permitir fazer pesquisas agrupadas por nome de laboratório. A variável composicao deve receber uma string de carateres (50 no máximo) e vai guardar a fórmula do medicamento caso seja conhecida. A variável posologia deve receber uma string de carateres (50 no máximo) e vai guardar a quantidade diária recomendada quando se utiliza o medicamento. A variável indicacoes deve receber uma string de carateres (50 no máximo) e vai guardar as aplicações conhecidas para o uso do medicamento caso sejam conhecidas. A variável contraIndicacoes deve receber uma string de carateres (50 no máximo) e vai guardar os efeitos indesejáveis conhecidos do medicamento caso estes sejam conhecidos. A variável anterior do tipo apontador para a estrutura Med, será o apontador para o endereço de memória do registo anterior na lista duplamente ligada. A variável seguinte do tipo apontador para a estrutura Med, será o apontador para o endereço de memória do registo seguinte na lista duplamente ligada. A variável numero deve receber um inteiro e guarda a identificação numérica do princípio ativo inserido. A inserção deste código será limitada entre 1 e 999 por opção e tal como na estrutura anterior não poderão ser introduzidos códigos repetidos. A variável designacao deve receber uma string de carateres (50 no máximo) e vai guardar o nome do princípio ativo inserido no sistema. Estes princípios podem ser já ou não existentes na estrutura Med, pois as duas estruturas são independentes. A variável descricao deve receber uma string de carateres (100 no máximo) e vai guardar uma breve descrição sobre o princípio ativo. Esta descrição deve ser a mais
  • 51. Cap. II – Descrição Técnica 43 breve e esclarecedora possível, uma vez que aparecerá no menu de seleção quando se introduz um novo medicamento. A variável ant do tipo apontador para a estrutura Principios, será o apontador para o endereço de memória do registo anterior na lista duplamente ligada. A variável seg do tipo apontador para a estrutura Principios, será o apontador para o endereço de memória do registo seguinte na lista duplamente ligada. 2.2 Funções e procedimentos Para a implementação do programa, foi necessário desenvolver uma série de funções e procedimentos, tanto para a estrutura Med como para a estrutura Principios. Apresenta-se um resumo das rotinas desenvolvidas pela ordem que aparecem no código fonte. 2.2.1 Inserir registo no início da lista ligada (Med) Este procedimento permite inserir um novo registo no início da lista duplamente ligada como foi previamente definido, ao mesmo tempo que atualiza os apontadores da cabeça da lista (início) e da cauda da lista (fim). 2.2.2 Inserir registo no início da lista ligada (Principios) Este procedimento é similar ao anterior mas para a estrutura dos princípios ativos. Grande parte das rotinas estará duplicada devido ao uso de duas estruturas diferentes. 2.2.3 Inserir novo medicamento Este procedimento permite ao utilizador introduzir dados num novo registo na estrutura Med. São solicitados os dados ao utilizador, que irão apresentar restrições de introdução relativamente ao código, e caso a lista ligada Principios não se encontre vazia o utilizador pode selecionar o princípio ativo de entre um menu que será apresentado. Após cada inserção, a lista é gravada em ficheiro de texto e é solicitado ao utilizador se deseja introduzir consecutivamente mais registos.
  • 52. Cap. II – Descrição Técnica 44 2.2.4 Inserir novo princípio ativo Este procedimento permite ao utilizador introduzir dados num novo registo da estrutura Principios. Os dados introduzidos terão restrições relativamente ao número que terá de ser limitado entre 1 e 999 e não poderá ser repetido. Após cada inserção é solicitado ao utilizador se pretende introduzir mais registos. 2.2.5 Listar medicamentos Este procedimento imprime na consola todos os registos presentes na estrutura Med caso a lista ligada não se encontre vazia. 2.2.6 Listar princípios ativos Este procedimento imprime na consola todos os registos presentes na estrutura Principios caso a lista ligada não se encontre vazia. 2.2.7 Gravar estrutura de medicamentos Este procedimento grava em formato de ficheiro de texto o conteúdo da lista ligada correspondente à estrutura Med. 2.2.8 Gravar estrutura de princípios ativos Este procedimento grava em formato de ficheiro de texto o conteúdo da lista ligada correspondente à estrutura Principios. 2.2.9 Carregar dados de medicamentos Este procedimento caso tenha um ficheiro de texto válido disponível, carrega os dados presentes para a lista ligada da estrutura Med através do procedimento inserir registo no início da lista ligada. 2.2.10 Carregar dados de princípios ativos Tal como o procedimento anterior, este procedimento carrega os dados presentes para a lista ligada da estrutura Principios caso exista um ficheiro de texto válido. 2.2.11 Menu de princípios ativos Esta função apresenta inicialmente um menu, em que as opções são a listagem da lista ligada Princípios. Assim, o utilizador deve escolher um dos princípios ativos do
  • 53. Cap. II – Descrição Técnica 45 menu que será referenciado através do seu número. Após esta escolha ser realizada, a função retorna o valor dessa escolha. 2.2.12 Pesquisa de princípios ativos Passando o valor retornado da função anterior por parâmetro a esta função, consegue-se extrair o nome do princípio ativo que tinha sido selecionado anteriormente. A função de pesquisa vai assim retornar o nome do princípio ativo selecionado. 2.2.13 Remover medicamento Este procedimento permite remover um medicamento através do seu código. Se não houver medicamentos o procedimento não será executado. No final de cada remoção é solicitado ao utilizador se deseja continuar e se este for removendo medicamentos até a lista ligada ficar vazia irá aparecer uma mensagem informando que não existem mais medicamentos. 2.2.14 Remover princípio ativo Este procedimento é similar ao anterior, mas funciona para a lista ligada de princípios ativos. 2.2.15 Pesquisar medicamentos por laboratório Este procedimento foi criado para satisfazer o critério de agrupar os medicamentos por laboratórios. É pedido ao utilizador que insira o nome do laboratório e serão mostrados todos os medicamentos do mesmo laboratório. Caso não exista o laboratório selecionado será indicado que não existem medicamentos pertencentes a esse laboratório. 2.2.16 Pesquisa por múltiplos critérios Este procedimento permite ao utilizador efetuar pesquisas através da conjunção de dois critérios previamente definidos. Estes critérios podem ser escolhidos pelo utilizador e caso a conjunção de busca seja verdadeira ele vai mostrar o medicamento ou medicamentos encontrados. O modo de funcionamento deste procedimento será explicado mais detalhadamente posteriormente.
  • 54. Cap. II – Descrição Técnica 46 2.2.17 Alterar dados de medicamento Este procedimento permite alterar um dado do medicamento previamente definido pelo utilizador através do seu código. Esta funcionalidade é criada de modo ao utilizador poder alterar os dados diretamente a partir da aplicação sem ter de recorrer ao ficheiro de texto. 2.2.18 Alterar dados de princípios ativos Este procedimento é similar ao anterior, mas funciona para a estrutura Principios. 2.2.19 Validar código Esta função permite verificar se o código introduzido na estrutura Med já se encontra utilizada. Esta função tanto será usada para verificar se o código já existe, como para impedir que códigos repetidos sejam inseridos. 2.2.20 Validar número Esta função é muito similar à anterior mas neste caso verifica os números introduzidos na estrutura Principios. 2.2.21 Validar laboratório Esta função permite verificar se o laboratório introduzido pelo utilizador existe dentro da estrutura Med e serve para validar pesquisas que envolvam o nome do laboratório. 2.2.22 Validar operações com estrutura medicamentos Esta função é extramente simples, mas ao mesmo tempo importante, pois permite verificar se a lista ligada Med se encontra ou não vazia dentro de procedimentos em que a lista ligada não consta na sua assinatura. 2.2.23 Validar operações com estrutura princípios ativos Esta função é similar à anterior, mas verifica a lista ligada da estrutura Principios.
  • 55. Cap. II – Descrição Técnica 47 2.2.24 Selecionar critérios Este procedimento apenas mostra a parte gráfica do menu de opções quando o utilizador escolhe os critérios para a pesquisa. Foi desenvolvido para manter o código principal mais pequeno. 2.2.25 Menu alterar medicamentos Mais uma vez este procedimento apenas mostra a parte gráfica do menu de opções quando o utilizador escolhe a opção alterar dados de medicamentos. O motivo da criação deste procedimento foi o mesmo: manter o código principal mais pequeno. 2.2.26 Menu alterar princípios ativos Este procedimento é muito similar ao anterior mas apresenta os critérios a alterar para a estrutura Principios. 2.2.27 Inexistência de medicamentos Este procedimento foi criado para apresentar um cabeçalho que ia ser utilizado em diversas ocasiões, sempre que não houvesse medicamentos para listar. Para não estar constantemente a repetir o código foi criado o procedimento. 2.2.28 Inexistência de princípios ativos Este procedimento é similar ao anterior, mas o cabeçalho é referente à estrutura Principios, que surge sempre que não há princípios ativos a listar. 2.2.29 Continuar Este procedimento foi criado para evitar uma repetição excessiva do mesmo código ao longo do programa. O procedimento faz uma espera, pede ao utilizador que pressione uma tecla e a seguir limpa a consola. 2.2.30 Navegação nos menus Estes procedimentos e funções são rigorosamente semelhantes aos utilizados na primeira aplicação desenvolvida. A diferença comparativamente com esta aplicação é que aqui estão a ser utilizados três menus encadeados em que é possível navegar entre eles. Só é possível abandonar a aplicação a partir do primeiro menu devido à instrução exit selecionando a opção 0.
  • 56. Cap. II 48 3 Desenvolvimento Ao se desenvolver o programa, foi garantido que as estruturas de dados eram independentes e que a sua manipulação não entraria em conflito. A razão de uma segunda estrutura de dados é carregar diretamente o princípio ativo para a primeira estrutura, quando a segunda não for vazia. Ao mesmo tempo as duas estruturas podem ser consultadas e geridas de forma independente. O resultado final deste programa é o código fonte que se encontra no final do capítulo. As técnicas de programação foram baseadas na primeira aplicação, sendo que nesta secção apenas serão demonstradas as inovações desenvolvidas. 3.1 Declarações Foram declaradas 4 variáveis globais para as listas ligadas do tipo apontador: 2 para a estrutura Med com o endereço inicial nulo e 2 para a estrutura Principios. Med *aptInicio = NULL; Med *aptFim = NULL; Principios *aptInicio2 = NULL; Principios *aptFim2 = NULL; Estas declarações permitem manter atualizados os apontadores início e fim da lista para as duas estruturas sempre que é introduzido um novo registo. Isto é fundamental para quando se pretender remover um registo em qualquer das listas ligadas. 3.2 Inserir novo medicamento No procedimento inserir novo medicamento é declarada uma variável copia do tipo apontador para carater com endereço inicial nulo. void inserirMedicamento () { int cod; char nom[50], pa[50], om[100], lab[50]; char comp[50], pos[50], ind[50], ci[50]; char *copia = NULL; int chave, manter = 1, teste = 0, teste3 = 0; char escolha;
  • 57. Cap. II – Desenvolvimento 49 Este apontador irá receber o endereço de memória do princípio ativo selecionado, caso a lista ligada Principios não seja vazia quando o procedimento for executado. teste3 = validarOperacoesPrincipios (aptInicio2); if (teste3 == 1) { chave = menuPrincipios (aptInicio2); copia = pesquisaPrincipios (aptInicio2, chave); strcpy (pa, copia); } else { printf ("PRINCÍPIO ATIVO: "); gets (pa); fflush (stdin); } Esta é a parte realmente diferente no programa. Quando o utilizador for inserir o princípio ativo, é testado se a lista ligada Principios se encontra ou não vazia. Se esta não estiver vazia é invocada a função menuPrincipios que retorna a escolha do utilizador para a variável chave. Seguidamente, através da função pesquisaPrincipios, o endereço de memória do princípio ativo selecionado é guardado na variável copia. Finalmente o princípio ativo é copiado para a variável pa através da instrução strcpy e o programa prossegue. Caso a lista ligada de princípios esteja vazia é solicitado ao utilizador que introduza o princípio ativo manualmente. 3.3 Selecionar princípios ativos A função menuPrincipios lista todos os registos da lista ligada Principios como se fosse um menu permitindo ao utilizador fazendo uma escolha através do seu número. No final a função retorna o número selecionado.
  • 58. Cap. II – Desenvolvimento 50 int menuPrincipios (Principios *aptInicio2) { int escolhaNumero = 0; if (aptInicio2 != NULL) { printf ("n"); printf ("*****************************************************n"); printf ("* *n"); printf ("* SELECIONAR PRINCÍPIO ATIVO *n"); printf ("* *n"); printf ("*****************************************************n"); printf ("n"); while (aptInicio2 != NULL) { printf ("%d - %s: %sn", aptInicio2 -> numero, aptInicio2 -> designacao, aptInicio2 -> descricao); printf ("n"); aptInicio2 = aptInicio2 -> seg; } } printf ("nIntroduzir número: "); scanf ("%d", &escolhaNumero); fflush (stdin); printf ("n"); return (escolhaNumero); } 3.4 Pesquisa de princípios ativos A função pesquisaPrincipios percorre a lista ligada Principios enquanto a chave que recebe por parâmetro for diferente do número de cada um dos seus registos. Quando encontra uma equivalência se o registo não for nulo retorna a designação do princípio ativo. Caso contrário retornaria 0, que não irá acontecer neste programa pois apenas irá pesquisar chaves confirmadas. char *pesquisaPrincipios (Principios *aptInicio2, int chave) { while (aptInicio2 -> numero != chave) aptInicio2 = aptInicio2 -> seg; if (aptInicio2 != NULL) return (aptInicio2 -> designacao); return (0); }
  • 59. Cap. II – Desenvolvimento 51 3.5 Remover medicamentos Os procedimentos para remover (neste caso remover medicamento) terão dois testes: um para testar se a operação se justifica, caso contrário é sinal que não existem medicamentos e outro para verificar se o código de medicamento que se pretende remover existe. void remover (Med **endInicio, Med **endFim) { Med *aux = *endInicio; int manter3 = 1, apagar = 0, teste4 = 0, teste5 = 0; char escolha3; system ("cls"); teste4 = validarOperacoesMedicamentos (aptInicio); if (teste4 == -1) { naoExiste (); menu (); } else { No primeiro caso, se não existirem medicamentos, uma mensagem é impressa e o programa retorna ao menu de opções. No segundo caso, se o código não existir, é solicitado ao utilizador se pretende continuar ou retroceder. while ((aux != NULL) && (aux -> codigo != apagar)) aux = aux -> seguinte; if ((aux != NULL) && (aux -> anterior == NULL)) { *endInicio = aux -> seguinte; free (aux); } else if ((aux != NULL) && (aux -> seguinte == NULL)) { *endFim = aux -> anterior; aux -> anterior -> seguinte = NULL; free (aux); } else if ((aux!=NULL)&&(aux->seguinte==NULL)&&(aux->anterior==NULL)) { *endInicio = NULL; *endFim = NULL; free (aux); } else if (aux != NULL) { aux -> anterior -> seguinte = aux -> seguinte; aux -> seguinte -> anterior = aux -> anterior; free (aux); }
  • 60. Cap. II – Desenvolvimento 52 Se o código for válido, o programa corre a lista ligada enquanto o código a apagar for diferente do código do registo. Quando aparece uma equivalência existem 4 possibilidades: o registo estar no início da lista ligada (1ª condição), o registo estar no fim da lista ligada (2ª condição), só existir um registo (3ª condição) ou o registo estar numa posição algures a meio da lista ligada. Verificada essa condição, são executadas as instruções para religar a nova lista ligada sem o registo removido e o registo é apagado através da instrução free. 3.6 Pesquisa por múltiplos critérios O procedimento pesquisaMultiplos vai permitir efetuar pesquisas pela conjunção de dois critérios selecionados pelo utilizador. void pesquisaMultiplos (Med *aptInicio) { int criterio1=0, criterio2=0, caminho=0, cnt=0, teste9=0, teste10=0; teste9 = validarOperacoesMedicamentos (aptInicio); if (teste9 == -1) { naoExiste (); menu2 (); } else { selecionarCriterios (); printf ("nA: "); scanf ("%d", &criterio1); fflush (stdin); printf ("B: "); scanf ("%d", &criterio2); fflush (stdin); caminho = criterio1 * criterio2; Estes são dados a escolher ao utilizador através da invocação do procedimento selecionarCriterios. Após isto o utilizador deve introduzir duas escolhas que serão dois valores de 1 a 4. printf ("-----------------------------------------------------------n"); printf ("| 1 | Código |n"); printf ("-----------------------------------------------------------n"); printf ("| 2 | Nome |n"); printf ("-----------------------------------------------------------n"); printf ("| 3 | Princípio ativo |n"); printf ("-----------------------------------------------------------n"); printf ("| 4 | Laboratório |n"); printf ("-----------------------------------------------------------n");
  • 61. Cap. II – Desenvolvimento 53 Existem várias combinações que podem ser simplificadas através de um caminho de pesquisa. Para isso multiplica-se o valor das duas escolhas: Código * Nome 2 Nome * Princípio ativo 6 Código * Princípio ativo 3 Nome * Laboratório 8 Código * Laboratório 4 Princípio ativo * Laboratório 12 Como o código por definição é único, qualquer pesquisa envolvendo o código e o nome, apenas vai encontrar uma ocorrência. if (caminho == 2) // Pesquisa por código { int _cod; printf ("Código: "); scanf ("%d", &_cod); Se o caminho encontrado for 3, a pesquisa será por código e princípio ativo. else if (caminho == 3) // pesquisa por código/principio { int _ccod; char _ppat[50]; printf ("Código: "); scanf ("%d", &_ccod); fflush (stdin); printf ("Princípio ativo: "); gets (_ppat); Se o caminho encontrado for 4, a pesquisa será por código e laboratório. else if (caminho == 4) // pesquisa por código/laboratório { int _codd; char _labb[50]; printf ("Código: "); scanf ("%d", &_codd); fflush (stdin); printf ("Laboratório: "); gets (_labb); Se o caminho encontrado for 6, a pesquisa será por nome e princípio ativo. else if (caminho == 6) // pesquisa por nome/principio { char _nome[50], _pat[50]; printf ("Nome: "); gets (_nome); fflush (stdin); printf ("Princípio ativo: "); gets (_pat);
  • 62. Cap. II – Desenvolvimento 54 Se o caminho encontrado for 8, a pesquisa será por nome e laboratório. else if (caminho == 8) // pesquisa por nome/laboratório { char _name[50], _labot[50]; printf ("Nome: "); gets (_name); fflush (stdin); printf ("Laboratório: "); gets (_labot); Finalmente, se o caminho encontrado for 12, a pesquisa será por princípio ativo e laboratório. else if (caminho == 12) // pesquisa por princípio/laboratório { char _pat[50], _laborat[50]; printf ("Princício ativo: "); gets (_pat); fflush (stdin); printf ("Laboratório: "); gets (_laborat); 3.7 Validar laboratório As funções de validar operações e validar códigos/números já foram demonstradas no primeiro trabalho. No entanto esta é a primeira em que a validação é feita através da instrução strcmp, que é possível realizar através da inclusão da biblioteca string.h. int validarLaboratorio (Med *aptInicio, char *test3) { while (aptInicio != NULL) { if ((strcmp (aptInicio -> laboratorio, test3)) == 0) return (1); aptInicio = aptInicio -> seguinte; } return (0); } A instrução strcmp devolve 0 se ao comparar duas strings elas forem iguais e devolve 1 se elas forem diferentes. Assim, a lista ligada será percorrida enquanto a comparação for diferente de 0. Quando a strcmp devolver 0 significa que encontrou uma equivalência e nesse caso a função retorna 1. Caso não encontre nenhuma equivalência enquanto houver registos na lista ligada, a função retorna 0.
  • 63. Cap. II 55 4 Testes e Resultados 4.1 Menu de opções principal O menu de opções principal apresenta três funcionalidades fundamentais (inserir, remover ou alterar medicamento) e capacidade de navegação para outros dois menus secundários (consultas e gestão de princípios ativos). Figura 10 – Menu de opções principal. 4.2 Inserir novo medicamento Esta funcionalidade permite inserir dados de um novo medicamento, escolhendo neste caso o principio ativo a partir de um menu. Figura 11 – Inserir novo medicamento.
  • 64. Cap. II – Testes e Resultados 56 4.3 Alterar dados de medicamentos Esta funcionalidade permite alterar os dados de um medicamento inserido. Neste exemplo o código do exame que se pretendia alterar não existia no sistema, logo é requerido ao utilizador se deseja continuar. Figura 12 – Alterar dados de medicamentos. 4.4 Pesquisa por laboratório Esta funcionalidade permite agrupar os medicamentos registados por laboratório, que é introduzido pelo utilizador. Este é um dos requisitos deste trabalho. Figura 13 – Pesquisa por laboratório.
  • 65. Cap. II – Testes e Resultados 57 4.5 Pesquisa por múltiplos critérios Esta funcionalidade permite pesquisar medicamentos por mais de um critério selecionados pelo utilizador. Neste caso seria o nome e o laboratório. Este era outro dos requisitos do trabalho. Figura 14 – Pesquisa por múltiplos critérios. 4.6 Listar princípios ativos Esta funcionalidade permite listar os princípios ativos registados na estrutura auxiliar do sistema. Não é um requisito obrigatório do trabalho. Figura 15 – Listar princípios ativos.
  • 66. Cap. II 58 5 Código fonte #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <locale.h> typedef struct Simposium { int codigo; char nome[50], principioAtivo[50], outrosMedicamentos[100], laboratorio[50]; char composicao[50], posologia[50], indicacoes[50], contraIndicacoes[50]; struct Simposium *anterior; struct Simposium *seguinte; } Med; typedef struct Generico { int numero; char designacao[50], descricao[100]; struct Generico *ant; struct Generico *seg; } Principios; Med *aptInicio = NULL; Med *aptFim = NULL; Principios *aptInicio2 = NULL; Principios *aptFim2 = NULL; void inserir (Med **endInicio, Med **endFim, int cod, char *nom, char *pa, char *om, char *lab, char *comp, char *pos, char *ind, char *ci); void inserirPrincipio (Principios **endInicio2, Principios **endFim2, int num, char *des, char *desc); void inserirMedicamento (); void inserirPrincipioAtivo (); void listar (Med *aptInicio); void listarPrincipios (Principios *aptInicio2); void gravar (Med *aptInicio); void gravarPrincipios (Principios *aptInicio2); void carregarSimposium (); void carregarGenerico (); int menuPrincipios (Principios *aptInicio2); char *pesquisaPrincipios (Principios *aptInicio2, int chave); void remover (Med **endInicio, Med **endFim); void removerPrincipio (Med **endInicio, Med **endFim); void pesquisaLaboratorio (Med *aptInicio); void pesquisaMultiplos (Med *aptInicio); void alterar (Med *aptInicio); void alterar2 (Principios *aptInicio2); int validarCodigo (Med *aptInicio, int test); int validarNumero (Principios *aptInicio2, int test2); int validarLaboratorio (Med *aptInicio, char *test3); int validarOperacoesMedicamentos (Med *aptInicio); int validarOperacoesPrincipios (Principios *aptInicio2);
  • 67. Cap. II – Código fonte 59 void selecionarCriterios (); void menuAlterar (); void menuAlterar2 (); void naoExiste (); void naoExiste2 (); void continuar (); void capa (); int fmenu (); void menu (); int fmenu2 (); void menu2 (); int fmenu3 (); void menu3 (); void inserir (Med **endInicio, Med **endFim, int cod, char *nom, char *pa, char *om, char *lab, char *comp, char *pos, char *ind, char *ci) { Med *novo; novo = (Med*) malloc (sizeof (Med)); novo -> codigo = cod; strcpy (novo -> nome, nom); strcpy (novo -> principioAtivo, pa); strcpy (novo -> outrosMedicamentos, om); strcpy (novo -> laboratorio, lab); strcpy (novo -> composicao, comp); strcpy (novo -> posologia, pos); strcpy (novo -> indicacoes, ind); strcpy (novo -> contraIndicacoes, ci); if (*endInicio == NULL) { novo -> seguinte = NULL; novo -> anterior = NULL; *endInicio = novo; *endFim = novo; } else { (*endInicio) -> anterior = novo; novo -> seguinte = *endInicio; novo -> anterior = NULL; *endInicio = novo; } } void inserirPrincipio (Principios **endInicio2, Principios **endFim2, int num, char *des, char *desc) { Principios *novo2; novo2 = (Principios*) malloc (sizeof (Principios)); novo2 -> numero = num; strcpy (novo2 -> designacao, des); strcpy (novo2 -> descricao, desc); if (*endInicio2 == NULL) { novo2 -> seg = NULL; novo2 -> ant = NULL;
  • 68. Cap. II – Código fonte 60 *endInicio2 = novo2; *endFim2 = novo2; } else { (*endInicio2) -> ant = novo2; novo2 -> seg = *endInicio2; novo2 -> ant = NULL; *endInicio2 = novo2; } } void inserirMedicamento () { int cod; char nom[50], pa[50], om[100], lab[50]; char comp[50], pos[50], ind[50], ci[50]; char *copia = NULL; int chave, manter = 1, teste = 0, teste3 = 0; char escolha; system ("cls"); printf ("n"); printf ("*******************************************************n"); printf ("* *n"); printf ("* INSERIR DADOS DO MEDICAMENTO *n"); printf ("* *n"); printf ("*******************************************************n"); printf ("n"); while (manter == 1) { printf ("CÓDIGO: "); scanf ("%d", &cod); fflush (stdin); teste = validarCodigo (aptInicio, cod); if (teste == 1) { printf ("nCódigo já se encontra em utilizaçãonn"); manter = 1; } else if ((cod < 1) || (cod > 9999)) { printf ("nIntroduza código entre 1 e 9999nn"); manter = 1; } else manter = 0; } printf ("nNOME: "); gets (nom); fflush (stdin); printf ("n"); teste3 = validarOperacoesPrincipios (aptInicio2);