Instituto Politécnico do Cávado e do Ave
Escola Superior de Tecnologia
Engenharia Eletrotécnica e de Computadores
Estrutur...
ii
Resumo
Este trabalho, teve como objetivo o desenvolvimento de aplicações em
linguagem C, utilizando estruturas de dados...
iii
Índice
Resumo............................................................................................................
iv
2.2.11 Validar operações com a lista ligada ........................................................ 11
2.2.12 Apresent...
v
5 Código fonte ............................................................................................................
vi
2.2.20 Validar número......................................................................................... 46
2.2.2...
vii
4.6 Listar princípios ativos ..................................................................................... 57
...
viii
3.4 Listar atletas......................................................................................................
1
Introdução
As linguagens de programação são uma forma de enviar instruções para um
computador ou processador, usando mét...
Introdução
2
1 Linguagem C
Uma das linguagens de programação mais utilizadas no mundo é a linguagem C.
Existem, outras ain...
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...
Introdução
4
terá endereço NULL. A figura seguinte representa o esquema das ligações necessárias
para desenvolver uma list...
Introdução
5
Figura 2 – Esquema de uma LDL.
Vantagens das LDL:
Maior controlo dos dados presentes na lista ligada.
Existe ...
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...
Cap. I
8
2 Descrição Técnica
Para desenvolver o problema proposto, foi utilizada uma estrutura de dados
baseada numa lista...
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 d...
Cap. I – Descrição Técnica
10
2.2.3 Introduzir dados num registo pelo utilizador
Este é um dos procedimentos principais do...
Cap. I – Descrição Técnica
11
como o procedimento anterior, caso a lista ligada se encontre vazia não vai ser
executado.
2...
Cap. I
12
3 Desenvolvimento
Para desenvolver o programa e para que este funcione corretamente, foi
necessário que todos os...
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...
Cap. I – Desenvolvimento
14
3.4 Restrições
Dentro do procedimento inserir exame vão existir algumas restrições como se
pod...
Cap. I – Desenvolvimento
15
3.5 Listar exames
O procedimento listar exames é extremamente simples. Uma vez que ele já
rece...
Cap. I – Desenvolvimento
16
3.7 Carregar exames
O procedimento carregar exames, vai permitir inserir os dados presentes no...
Cap. I – Desenvolvimento
17
void pesquisaPaciente (Exames *apt)
{
int chave, teste2 = 1;
char escolha2;
system ("cls");
te...
Cap. I – Desenvolvimento
18
A solução encontrada foi limitar esse período através de duas chaves: uma
inferior e outra sup...
Cap. I – Desenvolvimento
19
for validado o utilizador tem duas opções: recomeçar, procurando um código válido ou
abandonar...
Cap. I – Desenvolvimento
20
3.12 Validar operação
Este procedimento que é largamente utilizado, testa se a lista ligada é ...
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 qu...
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 ...
Cap. I – Testes e Resultados
23
4.5 Pesquisa por data
A pesquisa por período de tempo permite encontrar exames realizados ...
Cap. I
24
5 Código fonte
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <locale.h>...
Cap. I – Código fonte
25
Exames *inserirFim (Exames *apt, int cod, char *dep, char *pac, int id,
char *tec, int d, int m, ...
Cap. I – Código fonte
26
{
manter = 1;
printf ("nATENÇÃO! Código já foi introduzidonn");
}
else
manter = 0;
}
manter = 1;
...
Cap. I – Código fonte
27
fflush (stdin);
if ((a < 2000) || (a > 2099))
{
manter = 1;
printf ("nATENÇÃO! Introduza um ano e...
Cap. I – Código fonte
28
printf ("NOME DO PACIENTE: %sn", apt -> paciente);
printf ("IDENTIFICAÇÃO DO PACIENTE: %dn", apt ...
Cap. I – Código fonte
29
ListaLigada=inserirFim(ListaLigada,cod,dep,pac,id,tec,d,m,a,res);
}
fclose (ficheiro);
}
else
pri...
Cap. I – Código fonte
30
else
{
system ("cls");
menu ();
}
}
}
void pesquisaData (Exames *apt)
{
int chaveDiaInf, chaveMes...
Cap. I – Código fonte
31
printf ("nATENÇÃO! Introduza um mês entre 1 e 12nn");
}
else
manter2 = 0;
}
manter2 = 1;
while (m...
Cap. I – Código fonte
32
while (manter2 == 1)
{
printf ("Ano: ");
scanf ("%d", &chaveAnoSup);
fflush (stdin);
if ((chaveAn...
Cap. I – Código fonte
33
void alterar (Exames *apt)
{
int _cod, _id, _d, _m, _a;
char _dep[50], _pac[50], _tec[50], _res[1...
Cap. I – Código fonte
34
while (manter3 == 1)
{
printf ("Selecione opção: ");
scanf ("%d", &modificar);
fflush (stdin);
if...
Cap. I – Código fonte
35
else if ((apt != NULL) && (modificar == 6))
{
printf ("nNovos resultados: ");
gets (_res);
fflush...
Cap. I – Código fonte
36
printf ("| 1 | Departamento |n");
printf ("------------------------------------------------------...
Cap. I – Código fonte
37
system ("cls");
}
int fmenu ()
{
char op[10];
int manter4 = 1, i = 0, t = 0, opc = 0;
while (mant...
Cap. I – Código fonte
38
else
manter4 = 0;
}
}
return (opc);
}
void menu ()
{
int opcao = 0;
opcao = fmenu ();
while (opca...
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 ...
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 ...
Cap. II – Descrição Técnica
42
A variável outrosMedicamentos deve receber uma string de carateres (100 no
máximo) e vai gu...
Cap. II – Descrição Técnica
43
breve e esclarecedora possível, uma vez que aparecerá no menu de seleção quando se
introduz...
Cap. II – Descrição Técnica
44
2.2.4 Inserir novo princípio ativo
Este procedimento permite ao utilizador introduzir dados...
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...
Cap. II – Descrição Técnica
46
2.2.17 Alterar dados de medicamento
Este procedimento permite alterar um dado do medicament...
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çõ...
Cap. II
48
3 Desenvolvimento
Ao se desenvolver o programa, foi garantido que as estruturas de dados eram
independentes e q...
Cap. II – Desenvolvimento
49
Este apontador irá receber o endereço de memória do princípio ativo
selecionado, caso a lista...
Cap. II – Desenvolvimento
50
int menuPrincipios (Principios *aptInicio2)
{
int escolhaNumero = 0;
if (aptInicio2 != NULL)
...
Cap. II – Desenvolvimento
51
3.5 Remover medicamentos
Os procedimentos para remover (neste caso remover medicamento) terão...
Cap. II – Desenvolvimento
52
Se o código for válido, o programa corre a lista ligada enquanto o código a
apagar for difere...
Cap. II – Desenvolvimento
53
Existem várias combinações que podem ser simplificadas através de um caminho
de pesquisa. Par...
Cap. II – Desenvolvimento
54
Se o caminho encontrado for 8, a pesquisa será por nome e laboratório.
else if (caminho == 8)...
Cap. II
55
4 Testes e Resultados
4.1 Menu de opções principal
O menu de opções principal apresenta três funcionalidades fu...
Cap. II – Testes e Resultados
56
4.3 Alterar dados de medicamentos
Esta funcionalidade permite alterar os dados de um medi...
Cap. II – Testes e Resultados
57
4.5 Pesquisa por múltiplos critérios
Esta funcionalidade permite pesquisar medicamentos p...
Cap. II
58
5 Código fonte
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <locale.h...
Cap. II – Código fonte
59
void selecionarCriterios ();
void menuAlterar ();
void menuAlterar2 ();
void naoExiste ();
void ...
Cap. II – Código fonte
60
*endInicio2 = novo2;
*endFim2 = novo2;
}
else
{
(*endInicio2) -> ant = novo2;
novo2 -> seg = *en...
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
Próximos SlideShares
Carregando em…5
×

Estruturas de dados dinâmicos em linguagem C

494 visualizações

Publicada em

Trabalho para a UC de Programação I
Paulo Lima
IPCA, 2013

Publicada em: Engenharia
0 comentários
2 gostaram
Estatísticas
Notas
  • Seja o primeiro a comentar

Sem downloads
Visualizações
Visualizações totais
494
No SlideShare
0
A partir de incorporações
0
Número de incorporações
2
Ações
Compartilhamentos
0
Downloads
0
Comentários
0
Gostaram
2
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

Estruturas de dados dinâmicos em linguagem C

  1. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 14. 6 Capítulo I Listas ligadas simples Gestão de um arquivo de exames de diagnóstico médico
  15. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 47. 39 Capítulo II Listas duplamente ligadas Gestão de um simposium de medicamentos genéricos
  48. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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);

×