A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Aula 14 Programação Baseada em Objectos Desenho de TAD.

Apresentações semelhantes


Apresentação em tema: "Aula 14 Programação Baseada em Objectos Desenho de TAD."— Transcrição da apresentação:

1 Aula 14 Programação Baseada em Objectos Desenho de TAD

2 2003/2004 Introdução à Programação 2 Desenvolver uma calculadora Operações: + – adição - – subtracção / – divisão * – multiplicação ^ – potenciação Suporte para double (incluindo negativos) Parênteses proibidos Expressões de cin Resultados em cout Expressões terminam em ; ou. Símbolo. termina execução da calculadora

3 2003/2004 Introdução à Programação 3 Exemplo Entrada: ; 2 * 2.5. Saída: 4 5

4 2003/2004 Introdução à Programação 4 Exercício Qual o resultado de 2 * * 5 ^ 2 ; ? E se os símbolos forem lidos um de cada vez? (Símbolos são valores ou operadores, incluindo terminadores)

5 2003/2004 Introdução à Programação 5 Cálculo de expressão Símbolo lido: 1

6 2003/2004 Introdução à Programação 6 Cálculo de expressão Que fazer aos símbolos lidos? Ao 1 e ao +? É necessário guardá-los algures! Símbolo lido: +

7 2003/2004 Introdução à Programação 7 Cálculo de expressão Podemos calcular já 1 + 4? Não! Depende do que se segue! Símbolo lido: 4

8 2003/2004 Introdução à Programação 8 Cálculo de expressão Calcular já teria sido asneira! A não ser que se tivesse lido 1 * 4, ou se o símbolo lido fosse + Nesse caso podíamos fazer já o cálculo, e escusávamos de memorizar tantos símbolos Símbolo lido: * Memorizar… No nosso programa teremos de guardar os símbolos algures!

9 2003/2004 Introdução à Programação 9 Cálculo de expressão E a saga continua Símbolo lido: 3

10 2003/2004 Introdução à Programação 10 Cálculo de expressão Podemos calcular o produto anterior, ou seja, 4 * 3 ! O resultado do produto tem de ser guardado O produto é o dos dois últimos valores lidos Regra: Ao ler um operador, podemos calcular os operadores em espera enquanto forem de precedência maior ou igual Símbolo lido: / Por ordem inversa à da leitura! Podem-se empilhar os operadores!

11 2003/2004 Introdução à Programação 11 Cálculo de expressão Mais uma vez é necessário guardar o valor Se a próxima operação for, por exemplo, +, a divisão é calculada entre 12 e 2, que foram os últimos valores considerados Símbolo lido: 2 Também se podem empilhar os valores!

12 2003/2004 Introdução à Programação 12 Regressemos ao início Vamos recomeçar o cálculo, mas equipando- nos com duas pilhas: Pilha dos operadores Pilha dos valores

13 2003/2004 Introdução à Programação 13 valoresoperadores Cálculo de expressão Lido um valor, há que colocá-lo na respectiva pilha Símbolo lido: 1

14 2003/2004 Introdução à Programação 14 valoresoperadores Cálculo de expressão Lido um operador, há que verificar se há algum outro de maior ou igual precedência na pilha Como não há, há que o colocar na pilha apropriada Símbolo lido: + 1

15 2003/2004 Introdução à Programação 15 valoresoperadores Cálculo de expressão Valores vão sempre para a pilha Símbolo lido: 4 1+

16 2003/2004 Introdução à Programação 16 valoresoperadores Cálculo de expressão Como a multiplicação tem maior precedência que a soma, que está no topo da pilha, não se pode ainda realizar a soma É necessário, de qualquer forma, colocar a multiplicação no topo da pilha Símbolo lido: * 1+ 4

17 2003/2004 Introdução à Programação 17 valoresoperadores Cálculo de expressão É um valor… Símbolo lido: *

18 2003/2004 Introdução à Programação 18 valoresoperadores Cálculo de expressão No topo da pilha há um operador com igual precedência Antes de guardar a nova operação na pilha, efectua-se a do topo e guarda-se o resultado Símbolo lido: / 1+ 4* 3 = 12

19 2003/2004 Introdução à Programação 19 valoresoperadores Cálculo de expressão Valores vão directos para a pilha, como sempre Símbolo lido: /

20 2003/2004 Introdução à Programação 20 valoresoperadores Cálculo de expressão Como a potenciação tem maior precedência que a divisão, que está no topo da pilha, não se pode ainda realizar a divisão É necessário, de qualquer forma, colocar a potenciação no topo da pilha Símbolo lido: ^ 1+ 12/ 2

21 2003/2004 Introdução à Programação 21 valoresoperadores Cálculo de expressão Pilha com ele! Símbolo lido: / 2^

22 2003/2004 Introdução à Programação 22 valoresoperadores Cálculo de expressão Têm de se realizar todas as operações com precedência maior ou igual! Símbolo lido: / 2^ 3 = 8

23 2003/2004 Introdução à Programação 23 valoresoperadores Cálculo de expressão Têm de se realizar todas as operações com precedência maior ou igual! Símbolo lido: / 8 = 1,5

24 2003/2004 Introdução à Programação 24 valoresoperadores Cálculo de expressão Têm de se realizar todas as operações com precedência maior ou igual! Depois, guarda-se a operação na pilha Símbolo lido: ,5 = 2,5

25 2003/2004 Introdução à Programação 25 valoresoperadores Cálculo de expressão Mais um… Símbolo lido: 2 2,5-

26 2003/2004 Introdução à Programação 26 valoresoperadores Cálculo de expressão Ao atingir o símbolo. (ponto), efectuam-se todas as operações que restam na pilha Símbolo lido:. 2,5- 2 = 0,5

27 2003/2004 Introdução à Programação 27 valoresoperadores Cálculo de expressão Ao atingir o símbolo. (ponto), efectuam-se todas as operações que restam na pilha O resultado retira-se da pilha dos valores: Símbolo lido: 0,5

28 2003/2004 Introdução à Programação 28 E agora? É necessário escrever o programa… Mas já se sabe que ferramentas estão em falta: Um TAD para representar operadores Um TAD para representar uma calculadora E…

29 2003/2004 Introdução à Programação 29 TAD Operador Representa operadores (binários) que podem ser +, -, *, / ou ^ Construtor deve receber símbolo indicando operação a realizar Deve possuir operação para calcular resultado da sua aplicação a dois operandos double

30 2003/2004 Introdução à Programação 30 TAD Operador /** Representa um operador aritmético, com o qual se podem realizar ?. */ class Operador { public: … };

31 2003/2004 Introdução à Programação 31 Construtor Operador::Operador() /** … */ class Operador { public: /** Constrói um novo operador correspondente ao símbolo símbolo pertence a { '+', '-', '*', '/', '^' Operador é o operador representado por símbolo. */ explicit Operador(char const símbolo); … }; Código possível: Operador multiplicação(*); A utilização de explicit impede a conversão implícita de char em Operador.

32 2003/2004 Introdução à Programação 32 Operação Operador::operator()() /** … */ class Operador { public: … /** Devolve o resultado do operador quando aplicado aos operandos *this Operador ( / ) operando_direito operator() = operando_esquerdo *this operando_direito. */ double operator()(double const operando_esquerdo, double const operando_direito) const; … }; O operador parênteses é usado na invocação de rotinas. É um operador n-ário, que pode ser sobrecarregado! Código possível: Operador multiplicação(*); cout << multiplicação(2.0, 3.0) << endl; Chiça!

33 2003/2004 Introdução à Programação 33 Operação Operador::operator<() /** … */ class Operador { public: … /** Verifica se o operador tem menor precedência que o operador operador< = (precedência de *this é menor que a de outro_operador ). */ bool operator<(Operador const& outro_operador) const; … }; Código possível: Operador multiplicação(*); Operador adição(+); if(adição < multiplicação) …

34 2003/2004 Introdução à Programação 34 Operação Operador::operator==() /** … */ class Operador { public: … /** Verifica se o operador é igual ao operador dado. Note-se que a >= b e b >= a não implica que a == b, mas sim que a e b têm a mesma operador== = ( *this representa o mesmo operador que outro_operador ). */ bool operator==(Operador const& outro_operador) const; … }; Código possível: Operador multiplicação(*); Operador adição(+); if(adição == multiplicação) …

35 2003/2004 Introdução à Programação 35 Operação Operador::símboloÉVálido() /** … */ class Operador { public: … /** Verifica se um símbolo é representação de algum dos operadores símbolo pertence a { '+', '-', '*', '/', '^' }. */ static bool símboloÉVálido(char const símbolo); … }; Código possível: char símbolo; cin >> símbolo; if(not Operador::símboloÉVálido(símbolo)) cout << … << endl; else { Operador operador(símbolo); … } Um membro qualificado com static diz-se de classe. Se for uma operação, não tem instância implícita. As únicas diferenças para uma rotina não-membro são os privilégios de acesso a membros privados e o nome qualificado com o nome da classe.

36 2003/2004 Introdução à Programação 36 TAD Operador : Implementação /** Representa um operador aritmético, com o qual se podem realizar símbolo pertence a { '+', '-', '*', '/', '^' }. */ class Operador { … private: /** Indica se o invariante da classe é símbolo pertence a { '+', '-', '*', '/', '^' }. */ bool cumpreInvariante() const; char símbolo; };

37 2003/2004 Introdução à Programação 37 Construtor Operador::Operador() inline Operador::Operador(char const símbolo) : símbolo(símbolo) { assert(símboloÉVálido(símbolo)); assert(cumpreInvariante()); }

38 2003/2004 Introdução à Programação 38 Método Operador::operator()() double Operador::operator()(double const operando_esquerdo, double const operando_direito) const { assert(cumpreInvariante()); assert(símbolo != '/' or operando_direito != 0); switch(símbolo) { case '+': return operando_esquerdo + operando_direito; case '-': return operando_esquerdo - operando_direito; case '*': return operando_esquerdo * operando_direito; case '/': return operando_esquerdo / operando_direito; case '^': return pow(operando_esquerdo, operando_direito); }

39 2003/2004 Introdução à Programação 39 Método Operador::operator<() inline bool Operador::operator<(Operador const& outro_operador) const { assert(cumpreInvariante()); switch(símbolo) { case '+': case '-': return outro_operador.símbolo == '*' or outro_operador.símbolo == '/' or outro_operador.símbolo == '^'; case '*': case '/': return outro_operador.símbolo == '^'; case '^': return false; }

40 2003/2004 Introdução à Programação 40 Método Operador::operator==() inline bool Operador::operator==(Operador const& outro_operador) const { assert(cumpreInvariante()); return símbolo == outro_operador.símbolo; }

41 2003/2004 Introdução à Programação 41 Método Operador::símboloÉVálido() inline bool Operador::símboloÉVálido(char const símbolo) { return símbolo == '+' or símbolo == '-' or símbolo == '*' or símbolo == '/' or símbolo == '^'; }

42 2003/2004 Introdução à Programação 42 Método Operador::cumpreInvariante() inline bool Operador::cumpreInvariante() const { return símboloÉVálido(símbolo); }

43 2003/2004 Introdução à Programação 43 TAD Calculadora Representa uma calculadora Para ser mais curto e legível, o código não verifica nenhum possível erro do utilizador!

44 2003/2004 Introdução à Programação 44 TAD Calculadora /** Representa uma calculadora que opera sobre expressões lidas do canal cin, escrevendo o resultado em cout. As expressões podem envolver os operadores binários +, -, *, / e ^ (potenciação). Não podem incluir parênteses. As expressões são separadas por ; (ponto-e-vírgula) e terminadas por. ?. */ class Calculadora { public: … };

45 2003/2004 Introdução à Programação 45 Operação Calculadora::executa() /** … */ class Calculadora { public: /** Executa a calculadora sobre expressões presentes no canal As expressões no canal cin têm de estar sintacticamente correctas, estar separadas por ; (ponto-e-vírgula) e a sua sequência deve ser terminada por. O canal cout contém os resultados de todas as expressões, um em cada linha. */ void executa(); … };

46 2003/2004 Introdução à Programação 46 TAD Calculadora : Implementação /** Representa uma calculadora que opera sobre expressões lidas do canal cin, escrevendo o resultado em cout. As expressões podem envolver os operadores binários +, -, *, / e ^ (potenciação). Não podem incluir parênteses. As expressões são separadas por ; (ponto-e-vírgula) e terminadas por. pilha_de_valores. empty () pilha_de_operadores. empty (). */ class Calculadora { … private: … /** Indica se o invariante da classe é pilha_de_valores. estáVazia () pilha_de_operadores. estáVazia (). */ bool cumpreInvariante() const; PilhaDeDouble pilha_de_valores; PilhaDeOperador pilha_de_operadores; };

47 2003/2004 Introdução à Programação 47 Operação Calculadora:: efectuaOperaçãoNoTopo() /** … */ class Calculadora { … private: /** Efectua operação correspondente ao operador que se encontra no topo da pilha de operadores usando como operandos os dois valores no topo da pilha de valores. O valor que se encontra no topo da pilha de valores é o operando direito, sendo o valor imediatamente abaixo o operando 1 pilha_de_operadores. altura () 2 pilha_de_valores. altura Pilha de valores deixou de conter os dois valores do topo, tendo sido colocado no lugar deles o resultado do operador do topo da pilha de operadores (que entretanto foi retirado) quando aplicado aos dois valores retirados (o primeiro valor retirado da pilha de valores é o operando direito). */ void efectuaOperaçãoNoTopo(); … };

48 2003/2004 Introdução à Programação 48 Operação Calculadora:: efectuaOperacoesDePrecedenciaMaiorOuIgualA() /** … */ class Calculadora { … private: … /** Efectua os cálculos de todos os operadores de precedência superior ou igual ao operador passado como n = pilha_de_operadores. altura () k = número de operadores na pilha de operadores com precedência superior ou igual a operador m = pilha_de_valores. altura () k + 1 pilha_de_operadores. altura () = n – k pilha_de_valores. altura () = m – k – 1. */ void efectuaOperaçõesDePrecedênciaMaiorOuIgualA( Operador const& operador); … };

49 2003/2004 Introdução à Programação 49 Operação Calculadora:: efectuaTodasAsOperações() /** … */ class Calculadora { … private: … /** Efectua os cálculos de todos os operadores que estão na n = pilha_de_operadores. altura () m = pilha_de_valores. altura () n + 1 <= pilha_de_operadores. estáVazia () pilha_de_valores. altura () = m – n – 1. */ void efectuaTodasAsOperações(); … };

50 2003/2004 Introdução à Programação 50 Método Calculadora::executa() void Calculadora::executa() { assert(cumpreInvariante()); char caractere; do { cin >> caractere; if(not cin.fail()) if(Operador::simboloÉVálido(caractere)) { // Processamento de operador. } else if(caractere == ';' or caractere == '.') { // Processamento de terminador. } else if(isdigit(caractere)) { // Processamento de valor. } } while(not cin.fail() and caractere != '.'); assert(cumpreInvariante()); }

51 2003/2004 Introdução à Programação 51 Método Calculadora::executa() … if(Operador::simboloÉVálido(caractere)) { efectuaOperaçõesDePrecedênciaMaiorOuIgualA(Operador(caractere)); pilha_de_operadores.põe(Operador(caractere)); } else if(caractere == ';' or caractere == '.') { efectuaTodasAsOperações(); cout << pilha_de_valores.itemNoTopo() << endl; pilha_de_valores.tiraItem(); } else if(isdigit(caractere)) { cin.putback(caractere); double valor; cin >> valor; pilha_de_valores.põe(valor); } …

52 2003/2004 Introdução à Programação 52 Método Calculadora:: efectuaOperaçãoNoTopo() void Calculadora::efectuaOperaçãoNoTopo() { assert(1 <= pilha_de_operadores.altura()); assert(2 <= pilha_de_valores.altura()); double operando_direito = pilha_de_valores.itemNoTopo(); pilha_de_valores.tiraItem(); double operando_esquerdo = pilha_de_valores.itemNoTopo(); pilha_de_valores.tiraItem(); Operador operador = pilha_de_operadores.itemNoTopo(); pilha_de_operadores.tiraItem(); pilha_de_valores.põe(operador(operando_esquerdo, operando_direito)); }

53 2003/2004 Introdução à Programação 53 Método Calculadora:: efectuaOperacoesDeMaiorPrecedenciaQue() void Calculadora::efectuaOperaçõesDePrecedênciaMaiorOuIgualA( Operador const& operador) { while(not pilha_de_operadores.estáVazia() and pilha_de_operadores.itemNoTopo() >= operador) efectuaOperaçãoNoTopo(); }

54 2003/2004 Introdução à Programação 54 Método Calculadora:: efectuaTodasAsOperações() void Calculadora::efectuaTodasAsOperações() { while(not pilha_de_operadores.estáVazia()) efectuaOperaçãoNoTopo(); assert(pilha_de_operadores.estáVazia()); }

55 2003/2004 Introdução à Programação 55 Método Calculadora:: cumpreInvariante() bool Calculadora::cumpreInvariante() const { return pilha_de_valores.estáVazia() and pilha_de_operadores.estáVazia(); }

56 2003/2004 Introdução à Programação 56 E as pilhas? Programa escrito usa-as Necessário desenvolvê-las Desenho de TAD será demonstrado com as pilhas

57 2003/2004 Introdução à Programação 57 Desenho de TAD Recomendável começar por escrever restante código assumindo que existem Recomendável também escrever programa de teste Ambos clarificam operações e comportamentos desejáveis, bem como a interface desejável

58 2003/2004 Introdução à Programação 58 Operações das pilhas Construir pilha vazia Verificar se está vazia Obter o item do topo Saber altura da pilha Pôr item na pilha Tirar o item do topo construtores predicados (inspectores) inspectores modificadores Começaremos por PilhaDeDouble

59 2003/2004 Introdução à Programação 59 TAD PilhaDeDouble : Teste de unidade int main() { PilhaDeDouble pilha; assert(pilha.estáVazia()); assert(pilha.altura() == 0); for(int i = 0; i != 10; ++i) { assert(pilha.altura() == i); pilha.poe(i); assert(pilha.itemNoTopo() == i); assert(not pilha.estáVazia()); assert(pilha.altura() == i + 1); } (continua)

60 2003/2004 Introdução à Programação 60 TAD PilhaDeDouble : Teste de unidade (continuação) assert(pilha.itemNoTopo() == 9); assert(not pilha.estáVazia()); assert(pilha.altura() == 10); for(int i = 9; i != -1; --i) { assert(pilha.itemNoTopo() == i); assert(not pilha.estáVazia()); assert(pilha.altura() == i + 1); pilha.tiraItem(); assert(pilha.altura() == i); } assert(pilha.estáVazia()); assert(pilha.altura() == 0); }

61 2003/2004 Introdução à Programação 61 TAD PilhaDeDouble /** Representa pilhas de [o invariante é um problema de implementação]. */ class PilhaDeDouble { public: typedef double Item; … }; Permite alterar o tipo dos itens com muita facilidade. Definir PilhaDeOperador torna-se trivial: a)Copiar classe PilhaDeDouble completa. b)Substituir PilhaDeDouble por PilhaDeOperador. c)Alterar definição de Item de double para Operador.

62 2003/2004 Introdução à Programação 62 TAD PilhaDeDouble : Construtores /** … */ class PilhaDeDouble { public: … /** Constrói pilha estáVazia (). */ PilhaDeDouble(); … };

63 2003/2004 Introdução à Programação 63 TAD PilhaDeDouble : Predicados /** … */ class PilhaDeDouble { public: … /** Indica se a pilha está estáVazia = *this está vazia. */ bool estáVazia() const; … };

64 2003/2004 Introdução à Programação 64 TAD PilhaDeDouble : Inspectores /** … */ class PilhaDeDouble { public: … /** Devolve o item que está no topo da ¬ estáVazia itemNoTopo idêntico ao item no topo de *this. */ Item const& itemNoTopo() const; /** Devolve altura da altura = altura de *this (número de itens). */ int altura() const; … };

65 2003/2004 Introdução à Programação 65 TAD PilhaDeDouble : Modificadores /** … */ class PilhaDeDouble { public: … /** Põe um novo item na pilha (no *this contém um item adicional no topo igual a novo_item. */ void põe(Item const& novo_item); /** Tira o item que está no topo da ¬ estáVazia *this contém os itens originais menos o do topo. */ void tiraItem(); private: … };

66 2003/2004 Introdução à Programação 66 TAD PilhaDeDouble : Implementação Fica como exercício

67 2003/2004 Introdução à Programação 67 Estrutura global do programa #include #include // define, >= e != à custa de < e de ==. #include #include // para isdigit(). #include // para pow(). #include … // outras inclusões necessárias para as pilhas. using namespace std; using namespace std::rel_ops; // para definições de <= etc. terem efeito. class Operador {…} // e respectivos métodos. class PilhaDeDouble {…} // e respectivos métodos. class PilhaDeOperador {…} // e respectivos métodos. class Calculadora {…} // e respectivos métodos. (continua)

68 2003/2004 Introdução à Programação 68 Estrutura global do programa (continuação) #ifdef TESTE int main() { // Testes das várias classes! } #else // TESTE int main() { Calculadora calculadora; calculadora.executa(); } #endif // TESTE Para compilar os testes usa-se um comando de compilação semelhante a: c++ -DTESTE …

69 2003/2004 Introdução à Programação 69 Programação procedimental Primeiro pensa-se nos algoritmos Depois pensa-se nos dados

70 2003/2004 Introdução à Programação 70 Programação baseada em objectos Primeiro pensa-se nos dados (TAD) Depois pensa-se nos algoritmos Frequentemente são os substantivos mais importantes que surgem na descrição do problema.

71 2003/2004 Introdução à Programação 71 Desenho de TAD TAD são módulos Designers e departamento marketing definem interface Engenharia desenvolve o mecanismo

72 2003/2004 Introdução à Programação 72 Desenho de TAD Surgem para auxiliar resolução de problema Resolução usada para sugerir operações necessárias no TAD Começa-se pelo teste de unidade Teste de unidade testa todas as operações do TAD Depois desenha-se a interface do TAD Finalmente implementa-se: Passo a passo, testando a cada passo Se necessário fazer implementação embrionária de métodos e rotinas (apenas instruções asserção e nas funções uma instrução de retorno).

73 2003/2004 Introdução à Programação 73 Alerta! Há pilhas na biblioteca do C++: #include using namespace std; int main() { stack pilha; pilha.push(1); pilha.push(2); while(not pilha.empty()) { cout << pilha.top() << endl; pilha.pop(); }

74 2003/2004 Introdução à Programação 74 Aula 14: Sumário Desenho de TAD: programação baseada em objectos Fases: Escrita de testes Declaração das operações suportadas, suas consequências, e forma de utilização: interface Definição dos atributos (representação) e dos métodos (mecanismo): implementação. Exemplo com pilhas. Definição de sinónimos de tipos com typedef Classe genérica stack Noções elementares de eXtreme Programming: Testes primeiro Desenvolvimento incremental


Carregar ppt "Aula 14 Programação Baseada em Objectos Desenho de TAD."

Apresentações semelhantes


Anúncios Google