Estruturas de funções I
Aula 13
Agenda
• Especificação de uma função • Estrutura de chamada de funções • Condições de retorno
• Funções de arrumação
Objetivo
Apresentar os conceitos relativos a interfaces de funções.
Referência
Modos de organizar programas - paradigmas
Verbete: paradigma
1. Modelo, padrão, estalão:
Paradigma de programação
• é um modelo ou forma de organizar programas
Paradigma procedural
• programas são modelados segundo estruturas de chamada de funções • freqüentemente cada função é um módulo (ex. FORTRAN)
• tende a gerar um volume grande de dados globais externos (COMMON) • encapsulamento é virtualmente impossível
Paradigma orientado a objetos
• programas são modelados segundo tipos abstratos de dados ou de classes de objetos
• pode-se encapsular os dados e as funções de apoio
• pode-se manipular instâncias de estruturas de dados (objetos)
Paradigma funcional
• programas são modelados segundo funções e associações de parâmetros, ex. Scheme, Lisp
Estrutura potencial de chamadas
Estrutura potencial de chamada
• definida pela relação função-chama-função • estática
• todas as chamadas conhecidas em tempo de compilação • dinâmica
• chamadas efetuadas e ainda ativas a cada momento da execução • chamadas dinâmicas utilizam variáveis do tipo referência para
função F3 F4 F5 F6 F1 F2 F7 MÓDULO 1 MÓDULO 2 MÓDULO 3 F8 F9 F10
• a figura mostra a estrutura potencial de chamadas, F1 é a origem • arco de chamada: seqüência de chamadas realizadas e ainda ativas • arco de chamadas recursivas indiretas: F9 -> F8 -> F3 -> F5 -> F9 • podem existir funções mortas ex: F10
• pode existir dependência circular entre módulos sem que isto configure uma recursão: F8 -> F3 -> F5 -> F6 -> F7
Função
Uma função é uma porção de código contida em um espaço de dados, • possui um nome
• possui uma assinatura • valor retornado • nome
• lista de parâmetros => tipos dos parâmetros int Func( int , float )
• a assinatura está associada a um de possivelmente vários corpos (código) • associação da implementação
• pode ser chamada (ativada) de diversos lugares
• na hora da chamada é estabelecida outra associação: a associação da chamada
• estática (tempo de compilação), caso normal de linguagens procedurais • dinâmica (tempo de execução), caso freqüente em linguagens
orientadas a objetos
• versionada - a associação pode depender da versão (DLL)
Chama F( float ) Associação da chamada F( float ) F( int ) Corpo
F( float ) F( float )Corpo F ( int )Corpo
Associação da implementação Associação da implementação Assinatura Assinatura
Função
Uma função pode
• retornar zero ou mais valores • receber zero ou mais parâmetros • alterar zero ou mais parâmetros
• utilizar ou alterar zero ou mais estados • variáveis membro de objetos • variáveis membro de classes • variáveis globais
• estados da plataforma de execução, exemplos: • cursor ligado / desligado
• arquivo aberto / fechado • arquivo existe / não existe
• janela: monitor inteiro / monitor parcial / minimizada • criar, ler, alterar ou destruir zero ou mais arquivos
• alocar / solicitar ou desalocar / liberar recursos • interagir com o usuário
• menus • diálogos • mensagens • . . .
Especificação de uma função
Objetivo da função
• pode ser idêntico ao nome da função
Acoplamento
• identifica todos os itens da interface e respectivos tipos
Condições do acoplamento
• Pré-condição ⇔ assertiva de entrada
• estabelece as condições que dados, estados e arquivos devem satisfazer imediatamente antes de iniciar a execução da função • Pós-condição⇔ assertiva de saída
• estabelece as condições que dados, estados e arquivos devem satisfazer ao terminar a execução da função.
Interface com o usuário
• todos os relatórios e mensagens (textos, sons, gráficos, animações, …) enviadas para o usuário
• todos os dados e comandos recebidos do usuário
• restrito à função sendo observada, evitando funções chamadas por esta função
Requisitos
• estabelecem as características e condições que a função deverá satisfazer
Hipóteses
• estabelecem as características e condições esperadas pela função
Restrições
• restringem a liberdade de escolha de projeto, implementação, ou controle da qualidade
Exemplo de especificação de uma função
/********************************************************************* *
* $FC Função: TBS Obter um string contido na tabela *
* $ED Descrição da função
* Procura a identificação de um string na tabela de strings. * Caso encontrado, copia-o para o espaço disponibilizado pelo * cliente.
* Não sendo encontrado copia o string com idString == 1; * valor default:
* "Identificação de string %d não foi encontrada." *
* Contido no arquivo de especificação de string: * DefinicaoDefault.defstr
*
* Caso este também não seja encontrado, copia o string ERRO_STRING * definido neste módulo. Valor default:
* "?!?!?" *
* $EP Parâmetros
* idString - identifica o string a ser procurado na tabela * dimString - é a dimensão máxima, incluindo o zero terminal, * que o string obtido poderá ter
* pString - ponteiro para espaço receptor do string com pelo * menos dimString bytes
*
* $FV Valor retornado
* Ver especificações das condições de retorno *
*********************************************************************/ TBS_tpCondRet TBS_ObterString( long idString ,
int dimString , char * pString ) ;
Pré e pós condições
Estabelecem as condições que dados e resultados devem satisfazer Devem ser especificadas no acoplamento
• condições do acoplamento
Podem ser fatoradas se envolverem relações complexas
Exemplos de pré-condições:
Tabela contém 0 ou mais símbolos.
Simbolo é uma seqüência de zero ou mais bytes quaisquer.
idSimbolo é um identificador em relação um para um com um símbolo existente.
Exemplo de pós-condições:
Se CondRet == OK Então
Tabela contém 1 ou mais símbolos Se Simbolo já figurava na tabela Então
idSimbolo é o valor associado ao Simbolo já existente na tabela Senão
Terá sido criado um novo valor para idSimbolo diferente de todos os demais identificadores registrados na tabela
Simbolo terá sido acrescentado à Tabela e associado ao idSimbolo criado
FimSe FimSe
Se CondRet != OK Então
Tabela não terá sido alterada
idSimbolo será igual a NIL_SIMBOLO FimSe
Especificação do acoplamento
Resumido, semelhante à programação
InserirSimbolo( Tabela, Simbolo ) ⇒ Tabela, IdSimbolo, CondRet
Por extenso separando entrada e saída
Inserir símbolo em uma tabela Recebe dados
Tabela - Tabela em que será inserido o símbolo Simbolo - Símbolo a inserir
Produz resultados
Tabela - Se não ocorreu erro e se o símbolo era novo: Tabela acrescida do símbolo
Se não ocorreu erro e o símbolo já existia, ou se ocorreu erro: a tabela não terá sido alterada
idSimbolo - Se não ocorreu erro: é a identificação do símbolo na tabela
Se ocorreu erro: é NIL_SIMBOLO
CondRet - Condição de retorno: ver tpCondTabela
Por extenso, segundo o padrão de especificação no livro
Inserir símbolo em uma tabela Tabela
ao entrar - Tabela em que será inserido o símbolo
ao sair - Se não ocorreu erro e se o símbolo era novo: Tabela acrescida do símbolo
Se não ocorreu erro e o símbolo já existia, ou se ocorreu erro:
a tabela não terá sido alterada Simbolo
ao entrar - Símbolo a inserir idSimbolo
ao sair - Se não ocorreu erro:
é a identificação do símbolo na tabela Se ocorreu erro:
é SIMBOLO_NIL CondRet
ao sair - Condição de retorno:
Interface com o usuário
Mensagens exibidas para o usuário • mensagens de erro ou advertência
• mensagens de feedback ou de estado do processamento • bolhas e mensagens de auxílio
Dados exibidos para o usuário • valores • tabelas • relatórios • diagramas • figuras • gráficos • animações • sinais sonoros • . . .
Dados recebidos do usuário Comandos recebidos do usuário
• menus • teclas • ícones • botões • voz • . . .
Estrutura do pseudo código de uma função
Crie uma estrutura de pseudo código para funções com algoritmos extensos • primeiro crie a estrutura
• depois preencha o código
// Extrair palavras chave
// Criar a lista de palavras chave // Ler primeiro caractere
// Gerar lista de palavras chave while ( tem caractere )
{
// Processar caractere corrente if ( Caractere é delimitador && Palavra chave vazia ) {
// Marcar o início de nova palavra chave } else if ( Caractere é delimitador
&& Palavra chave não está vazia ) {
// Registrar a palavra chave
} else if ( Caractere não é delimitador ) {
// Adicionar caractere à palavra } else
{
// Sinalizar erro de lógica: condição impossível } // if
// Ler próximo caractere } // while
// Ordenar a lista de palavras chave // Exibir a lista de palavras chave
Localizador
Localizador
• é um elemento de programa utilizado para localizar um elemento contido em algum conjunto ou estrutura de dados
• identificador
• um valor em correspondência um para um com o elemento procurado em memória
• chave
• um valor em correspondência um para um com o elemento procurado em algum arquivo
• referência
• um nome ou localizador alternativo para o elemento a ser localizado • ponteiro
• o endereço do elemento na memória • função de acesso
• uma função que computa o endereço do espaço de dados a partir de um ou mais parâmetros, exemplo
Exemplos
• idAluno identifica um determinado aluno no conjunto de todos os alunos • Alunos{ idAluno }
• Em C: ObterAluno( pAlunos, idAluno )
• Em C++ ou Java: Alunos.ObterAluno( idAluno ) • Arv{ pNo }
• TabSimb{ Simbolo }.Valor • *(TabSimb( Simbolo )).Valor
• ArquivoX{ Chave } => estrutura de pesquisa, ex.: BTREE • ArquivoX{ inxRegistro } => função fseek(...)
Conceitos básicos relacionados com funções
Condição de retorno
• é um valor retornado por uma função indicando o estado final de seu funcionamento. Exemplos:
• OK processamento normal
• ERRO_DADO dados fornecidos for a de sua especificação • ERRO_PRECISAO não se atingiu a precisão requerida
Exceção
• é uma condição de término especial indicando a ocorrência de uma anormalidade no processamento. Exemplo:
• falta de memória • erro de dispositivo
• deve ser tratada através de tratamento de exceções: try ... catch
Run-time
• é a definição e implementação da máquina virtual necessária para executar os programas
• passagem de parâmetros • retorno de valores
• retorno de condições de exceção
• como é realizada a amarração dinâmica
Amarração
• (binding) é a associação de um nome ao seu espaço de dados
• vinculação da assinatura de uma função a uma de suas implementações • vinculação do nome da função sendo chamada com a respectiva
assinatura
• pode ocorrer de forma estática
• a mesma implementação vinculada ao nome é chamada sempre • pode ocorrer de forma dinâmica
• escolhe-se a implementação em função do estado da execução e/ou da assinatura a cada vez que a chamada for realizada
Conceitos básicos relacionados com funções
Interface conceitual
• definição da interface de uma função sem preocupação com a sua implementação
• é tipicamente a especificação
InserirSimbolo( Tabela, Simbolo ) ⇒ Tabela, IdSimbolo, CondRet
Interface física
• é a implementação da interface conceitual, determinando a forma de realizar fisicamente a interface conceitual
• identificação dos parâmetros • identificação dos dados globais
• identificação dos dados persistentes (arquivo)
tpIdSimbolo InserirSimbolo( tpSimbolo Simbolo) Tabela global estático do módulo
CondRet - exceção
Interface implícita
• é formada pelos dados da interface diferentes de parâmetros e valor de retorno
• dados globais • estados
• arquivos
• interface com o usuário Estabelecimento das interfaces
• declaração => protótipo • definição => cabeçalho
• parâmetro formal => parâmetro • implementação => corpo da função
Condições de retorno e tratamento de exceção
typedef enum {
Leu_OK , /* Leitura normal */
Leu_EOF , /* Encontrou fim de arquivo antes de ler */ Leu_Erro /* Ocorreu erro de leitura */
} tpLeu ; . . .
tpLeu LerReg( FILE * ptArq , tpReg * ptReg ) {
if ( feof( ptArq )) {
memset( ptReg , 0xFF , sizeof( tpReg )) ; return Leu_EOF ;
} /* if */
fread( ptReg , ptArq , sizeof( tpReg ) , 1 ) ; if ( ioError != OK )
{
memset( ptReg , 0xFF , sizeof( tpReg )) ; return Leu_Erro
} /* if */
return Leu_OK ; } /* Função LerReg */
A função cliente contém o código:
Cond = LerReg( pArqA , pBuffer ) ; switch ( Cond )
{
case Leu_OK:
/* tratar o caso de leitura normal */ break ;
case Leu_Erro:
printf( "\nErro de leitura no arquivo: %s" , NomeArqA ) ; printf( "\nPrograma sendo cancelado" ) ;
Finalizar( 4 ) ; break ;
default:
printf( "\Erro de execução: LerReg condição desconhecida: %i" , Cond ) ;
printf( "\nPrograma sendo cancelado" ) ; Finalizar( 4 ) ;
Arrumação da casa (housekeeping)
Ao terminar a execução de um programa, componente ou função todos os
recursos alocados a este programa, componente ou função devem ser liberados • arquivos abertos
• dispositivos bloqueados • memória alocada
• recursos alocados
• semáforos, locks e outros elementos de sincronização
• estado do sistema para o que era antes de iniciar a execução • perfil de execução
Assegurar a liberação de recursos alocados é particularmente complexo quando o programa utiliza tratamento de exceções
• Pode-se utilizar um módulo de arrumação da casa para ajudar a resolver • De qualquer maneira é necessária disciplina ao programar