Home

Capítulo 3

image

Contents

1. cout lt lt n lt lt endl existem dois blocos de instru es o primeiro corresponde ao corpo da fun o main eo segundo sequ ncia de instru es executada condicionalmente de acordo com o valor de n O segundo bloco de instru es encontra se embutido no primeiro Cada vari vel tem um contexto de defini o As vari veis globais s o definidas no contexto do programas e as vari veis locais no contexto de um bloco de instru es Para todos os efeitos os par metros de uma rotina pertencem ao contexto do bloco de instru es correspondente ao corpo da rotina 3 2 14 mbito ou visibilidade de vari veis Cada vari vel tem um mbito de visibilidade determinado pelo contexto no qual foi definida As vari veis globais s o vis veis isto utiliz veis em express es desde a sua declara o at ao final do ficheiro ver se no Cap tulo 9lque um programa pode consistir de v rios ficheiros As vari veis locais por outro lado s o vis veis desde o ponto de defini o at chaveta de fecho do bloco de instru es onde foram definidas Por exemplo include lt iostream gt Note se que as vari veis globais tamb m podem ser definidas no contexto do ficheiro bastando para isso preceder a sua defini o do qualificador static Este assunto ser clarificado quando se discutir a divis o de um programa em ficheiros no Cap tulo 9 3 2 FUN ES E PROCEDIMENTOS ROTINAS
2. m int 5 O valor de d depois escrito no ecr na instru o 3 Finalmente atinge se o final da fun o main o que leva retirada da pilha destrui o de todas as vari veis at base uma vez que n o h nenhum endere o de retorno na pilha No final a pilha fica exactamente como no in cio vazia Exemplo recursivo Suponha se agora o seguinte exemplo que envolve a chamada fun o recursiva factorial finclude lt iostream gt using namespace std Devolve o factorial do inteiro passado como argumento Opre PC 0 lt n lt l2 post CO factorial n ou ainda factorial L 5 x int factorial int const n assert 0 lt n and n lt 12 if n 0 or n 1 1 return 1 2 return n factorial n 1 3 int main cout lt lt factorial 3 lt lt endl 4 Mais uma vez conveniente dividir a instru o 4 em duas sub instru es 122 CAP TULO 3 MODULARIZA O ROTINAS factorial 3 4A cout lt lt lt lt endl 4B uma vez que a fun o invocada antes da escrita do resultado no ecr Da mesma forma a instru o 3 pode ser dividida em duas sub instru es factorial n 1 3A return n 3B Ou seja include lt iostream gt using namespace std Devolve o factorial do inteiro passado como argumento pre PC 0 lt n lt 12 post CO factorial n ou ainda factorial IL y int factoria
3. void reduzFrac o int amp n int amp d assert 0 lt n and 0 lt d int const k mdc n d n k d k assert mdc n d 1 Mas e o primeiro termo que se refere aos valores originais de n e d H linguagens como Eif fel 11 nas quais as asser es correspondentes s condi es objectivo podem fazer recurso aos valores das vari veis no in cio da respectiva rotina usando se para isso uma nota o especial Em C n o poss vel faz lo infelizmente Por isso o primeiro termo da condi o objectivo ficar por verificar O procedimento escreveFrac o tem um problema o seu objectivo escrever no ecr N o f cil formalizar uma condi o objectivo que envolve altera es do ecr como se pode S comum usar se o truque de guardar o valor a devolver por uma fun o numa vari vel com o mesmo nome da fun o pois nesse caso a asser o tem exactamente o mesmo aspecto que a condi o objectivo 3 2 FUN ES E PROCEDIMENTOS ROTINAS 111 ver pela utiliza o de portugu s vern culo na condi o objectivo E ainda menos f cil escrever uma instru o de asser o nessas circunst ncias Este procedimento fica pois sem qualquer instru o de asser o Finalmente falta a fun o madc Neste caso a condi o objectivo faz uso de uma fun o matem tica mdc N o faz qualquer sentido escrever a instru o de asser o como se segue Calcula e d
4. A execu o deste programa leva seguinte mensagem de erro teste teste C 23 int mdc int int Assertion 0 lt m and O lt n Abort core dumped 105 failed claro que este tipo de mensagens muito mais til para o programador que o simples abortar do programa ou pior a produ o pelo programa de resultados errados 106 CAP TULO 3 MODULARIZA O ROTINAS Suponha se agora o programa original para o c lculo da soma de frac es mas j equipado com instru es de asser o verificando as pr condi es dos v rios m dulos que o comp em exceptuando os que n o imp em qualquer pr condi o finclude lt iostream gt using namespace std Reduz a frac o passada com argumento na forma de dois inteiros positivos Opre PC n n d d A0 lt n 0 lt d post CO amp 4 Amde n d 1 void reduzFrac o int amp n int amp d Escreve no ecr uma frac o no formato usual que lhe passada na forma de dois argumentos inteiros positivos Opre PC V ou seja nenhuma pr condi o post CO oecr cont m n d emque n e d s oosvaloresde n e d representados em base decimal void escreveFrac o int n int d Calcula e devolve o m ximo divisor comum de dois inteiros positivos passados como argumentos Opre PC 0 lt mad lt n post CO mdc mde m n int mdc int m int n Devolve o menor de dois inteiros passados como argumentos pre PC YV ousej
5. Para resolver este tipo de problemas onde de interesse que o valor das vari veis que s o usadas como argumentos seja alterado dentro de um procedimento existe o conceito de pas sagem de argumentos por refer ncia A passagem de um argumento por refer ncia indicada no cabe alho do procedimento colocando o s mbolo amp depois do tipo do par metro pretendido como se pode ver abaixo void troca int amp x int amp y int const auxiliar x x yi y auxiliar Ao invocar como anteriormente ver Figura 3 2 3 2 FUN ES E PROCEDIMENTOS ROTINAS 83 x int y int 1 2 indica que o valor fixo uma constante TD 1 int const auxiliar x x int y int auxiliar intffrozen 1 2 1 2 x y x int y int auxiliar intffrozen 2 2 1 3 y auxiliar x int y D auxiliar int frozen 2 1 1 ou x int y int Figura 3 1 Algoritmo usual de troca de valores entre duas vari veis x e y atrav s de uma constante auxiliar 84 CAP TULO 3 MODULARIZA O ROTINAS Int as Lob cs 23 a int b int invoca o de troca x int amp gt a int y int amp gt b int 1 J 2 int const auxiliar
6. gt 26 RSS Neste caso o programa aborta com uma mensagem de erro porque a pr condi o do procedi mento reduzFrac o foi violada Um programa n o deve abortar nunca Nunca mesmo De quem a responsabilidade disso acontecer neste caso Do utilizador do programa que desobedeceu introduzindo frac es negativas apesar de instru do para n o o fazer ou do pro gramador produtor da fun o main e consumidor do procedimento reduzF rac o A resposta correcta a segunda a culpa nunca do utilizador do programador Isto tem de ficar absolutamente claro o utilizador tem sempre raz o Como resolver o problema H duas solu es A primeira diz que deve ser o programador consumidor a garantir que os valores passados nos argumentos de reduzFrac o t m de ser positivos conforme se estabeleceu na sua pr condi o Em geral este o caminho certo embora neste caso se possa olhar para o problema com um pouco mais de cuidado e reconhecer que a redu o de frac es s deveria ser proibida se o denominador fosse nulo Isso implica naturalmente refazer o procedimento reduzFrac o relaxando a sua pr condi o O que ressalta daqui que quanto mais leonina forte uma pr condi o menos trabalho tem o programador produtor do m dulo e mais trabalho tem o programador consumidor Pelo contr rio se a pr condi o for fraca isso implica mais trabalho para o produtor e menos para o consumidor Em q
7. cout lt lt Introduza duas frac es int nl dl n2 d2 cin gt gt nl gt gt dl gt gt n2 gt gt d2 C lculo da frac o soma em termos m nimos Escrita do resultado Usou se um nica instru o para definir quatro vari veis do tipo int que guardar o os nu meradores e denominadores das duas frac es lidas o C permite definir v rias vari veis na mesma instru o De seguida pode se passar ao sub problema final da escrita do resultado Suponha se que sendo as frac es de entrada e Z se pretendia que surgisse no ecr A soma de 6 9 com 7 3 3 1 Ent o o problema pode ser resolvido como se segue include lt iostream gt using namespace std Calcula e escreve a soma em termos m nimos de duas frac es positivas lidas do teclado int main Leitura das frac es do teclado cout lt lt Introduza duas frac es int nly dl n2 a2 cin gt gt nL gt gt dl gt gt n2 gt gt d2 C lculo da frac o soma em termos m nimos Escrita do resultado cout lt lt A soma de escreveFrac o nl dl cout lt lt com escreveFrac o n2 d2 cout lt lt escreveFrac o cout lt lt lt lt endl 66 CAP TULO 3 MODULARIZA O ROTINAS Neste caso adiou se um problema admitiu se que est dispon vel algures um procedimento chamado escreveFrac o que escreve uma frac o no ecr ev
8. k d k Escreve no ecr uma frac o no formato usual que lhe passada na forma de dois argumentos inteiros positivos pre PC V ou seja nenhuma pr condi o post CO o ecr cont m n d emque n e d s oosvaloresde n e d representados em base decimal void escreveFrac o int n int d cout lt lt n lt lt lt lt d Calcula e escreve a soma em termos m nimos de duas frac es positivas lidas do teclado int main Leitura das frac es do teclado cout lt lt Introduza duas frac es ine nt dl n2 a2s cin gt gt nl gt gt dl gt gt n2 gt gt d2 reduzFrac o nl dl reduzFrac o n2 d2 3 2 FUN ES E PROCEDIMENTOS ROTINAS 89 C lculo da frac o soma em termos m nimos int n nl d2 n al int d qt d2 reduzFrac o n d Escrita do resultado cout lt lt A soma de escreveFfrac o nl d1 cout lt lt T com T3 escreveFrac o n2 d2 cout lt lt T T escreveFfrac o n d cout lt lt lt lt endl 3 2 12 Vari veis locais e globais Uma observa o cuidadosa dos exemplos anteriores revela que afinal main uma fun o Mas uma fun o especial no seu in cio que come a a execu o do programa Assim sendo verifica se tamb m que at agora s se definiram vari veis dentro de rotinas s vari veis que se definem no corpo de rotinas chama se vari veis locai
9. d cout lt lt lt lt endl O programa acima precisa ainda de ser corrigido Como se ver mais frente n o se podem definir m ltiplas vari veis com o mesmo nome no mesmo contexto Assim a vari vel k deve ser definida uma nica vez e reutilizada quando necess rio include lt iostream gt using namespace std Calcula e escreve a soma em termos m nimos de duas frac es positivas lidas do teclado int main Leitura das frac es do teclado cout lt lt Introduza duas frac es 70 CAP TULO 3 MODULARIZA O ROTINAS ant fil cdi 2 2 cin gt gt nl gt gt dl gt gt n2 gt gt d2 int k mdc nl dl nl k dl k k mdc n2 d2 n2 k d2 k C lculo da frac o soma em termos m nimos int n nl da2 n al ant d di d2 k mdc n d n k d k Escrita do resultado cout lt lt A soma de escreveFrac o n1 d1 cout lt lt com escreveFrac o n2 d2 COUT LL Md Mo escreveFrac o n d cout lt lt lt lt endl 3 2 2 Defini o de rotinas Antes de se poder utilizar uma fun o ou um procedimento necess rio defini lo antes de usar a aparelhagem h que fabric la Falta portanto definir a fun o mdc e o procedi mento escreveFrac o Um poss vel algoritmo para o c lculo do mdc de dois inteiros positivos foi visto no primeiro cap tulo A part
10. 5 Instru o 2 E constru da uma vari vel divisor tamb m inteira mas sem que seja iniciali zada pelo que cont m lixo j se viu que n o boa ideia n o inicializar isto apenas um exemplo Instru o 3 Esta instru o implica v rias ocorr ncias sequenciais pelo que se separa em duas partes mdc x 3 6 3A divisor 3B Instru o 3A invocada a fun o mdc 1 S o constru dos os par metros m e n que funcionam como quaisquer outras vari veis excepto quanto inicializa o 2 Cada um dos par metros m e n inicializado com o valor do argumento respectivo na lista de argumentos colocados entre par nteses na chamada da fun o Neste caso o par metro m inicializado com o valor 8 e o par metro n inicializado com o valor 6 3 A execu o do programa passa para a primeira instru o do corpo da fun o 4 O corpo da fun o executado A primeira instru o executada constr i uma nova vari vel k com lixo A fun o termina quando se atinge a chaveta final do seu corpo ou quando ocorre uma instru o de retorno que consiste na palavra chave return seguida de uma express o apenas no caso das fun es como se ver O valor dessa express o o valor calculado e devolvido pela fun o Neste caso o seu valor 2 valor de k depois da procura do mdc 5 Ao ser atingida a instru o de retorno a fun o termina 6 S o destru das as vari veis
11. N mero da linha do ficheiro C onde ocorreu o erro cabe alho Cabe alho da fun o ou procedimento onde ocorreu o erro s em alguns com piladores condi o Condi o que deveria ser verdadeira mas n o o era Deve se usar uma instru o de asser o para verificar a veracidade da pr condi o da fun o mdc Calcula e devolve o m ximo divisor comum de dois inteiros positivos passados como argumentos Opre PC 0 lt mad lt n post CO mdc mde m n int mdc int const m int const n assert 0 lt m and O lt n int k m nimo m n while m k 0 or n amp k 0 k return k Suponha se o seguinte programa usando a fun o mdc 3 2 FUN ES E PROCEDIMENTOS ROTINAS include lt iostream gt include lt cassert gt using namespace std Devolve o menor de dois inteiros passados como argumentos Opre PC V ou seja nenhuma pr condi o post CO m nimo a a lt b V m nimo b b lt a int m nimo int const a int const b if a lt b return a else return b Calcula e devolve o m ximo divisor comum de dois inteiros positivos passados como argumentos pre PC 0 lt mad lt n post CO mdc mde m n int mdc int const m int const n assert 0 lt m and O lt n int k m nimo m n while m k 0 or n amp k 0 k int main cout lt lt mdc 0 10 lt lt endl
12. autom ticos que extraem a documenta o de um programa a partir deste tipo especial de coment rio Da mesma forma as constru es pre e Qpost servem para identificar ao sistema autom tico de documenta o a pr condi o e a condi o objectivo que tamb m conhecida por p s condi o As condi es PC e CO funcionam como um contrato que o programador produtor da rotina estabelece com o seu programador consumidor Se o programador consumidor desta rotina garantir que as vari veis do pro grama respeitam a pr condi o PC imediatamente antes de a invocar o progra mador produtor desta rotina garante que a condi o objectivo CO ser verdadeira imediatamente depois de esta terminar Em particular existe um sistema de documenta o dispon vel em Linux chamado doxygen que de grande utilidade 76 CAP TULO 3 MODULARIZA O ROTINAS Esta vis o legalista da programa o est por tr s de uma metodologia relativamente recente de desenvolvimento de programas a que se chama desenho por contracto Em algumas lin guagens de programa o como o Eiffel as pr condi es e as condi es objectivo fazem parte da pr pria linguagem o que permite fazer a sua verifica o autom tica Na linguagem C um efeito semelhante embora mais limitado pode ser obtido usando as chamadas instru es de asser o discutidas mais abaixo 3 2 5 Integra o da fun o no programa Para que a fun o mdc p
13. consert lo isoladamente e 4 permite fabricar os m dulos em quantidades diferentes de modo produ o se adequar melhor procura e g hoje em dia os leitores de DVD vendem se mais que os CD que est o a ficar obsoletos 59 60 CAP TULO 3 MODULARIZA O ROTINAS Tamb m para o consumidor final do sistema a modulariza o traz vantagens 1 permite a substitui o de um nico m dulo do sistema quer por avaria quer por se pretender uma maior fidelidade usando por exemplo um melhor amplificador 2 em caso de avaria apenas o m dulo avariado fica indispon vel podendo se continuar a usar todos os outros excepto claro se o m dulo tiver um papel fundamental no sis tema 3 permite a evolu o do sistema por acrescento de novos m dulos com novas fun es e g poss vel acrescentar um leitor de DVD a um sistema antigo ligando o ao amplificador 4 evita a redund ncia pois os m dulos s o reutilizados com facilidade e g o amplificador amplifica os sinais do sintonizador leitor de DVD etc Estas vantagens n o s o exclusivas dos sistemas de alta fidelidade s o gerais Qualquer sis tema pode beneficiar de pelo menos algumas destas vantagens se for modularizado A arte da modulariza o est em identificar claramente que m dulos devem existir no sistema Uma boa modulariza o atribui uma nica fun o bem definida a cada m dulo minimiza as liga es entre os m dulos e maximiza a coes o
14. gt gt dl gt gt n2 gt gt d2 reduzFrac o nl dl reduzFrac o n2 d2 C lculo da frac o soma em termos m nimos int n nl da2 n dl int d dl a2 reduzFrac o n d Escrita do resultado cout lt lt A soma de escreveFfrac o nl d1 3 2 FUN ES E PROCEDIMENTOS ROTINAS 99 Cout lt lt T com T escreveFrac o n2 d2 cout lt lt T Te escreveFrac o n d cout lt lt lt lt endl void reduzFrac o int amp n int amp d int const k mdc n d n k d k void escreveFrac o int n int d cout lt lt n lt lt lt lt d int mdc int m int n int k if m lt n k m else k n while m k 0 or n k 0 gs return k Esta disposi o mais usual que a primeira Repare se que neste caso a documenta o das rotinas aparece junto com a sua declara o que essa documenta o fundamental para saber o que a rotina faz e portanto faz parte da interface da rotina Como uma declara o a especifica o completa da interface natural que seja a declara o a ser documentada e n o a defini o 3 2 18 Par metros constantes comum que os par metros de uma rotina n o mudem de valor durante a sua execu o Nesse caso bom h bito explicit lo tornando os par metros constantes Dessa forma enganos do programador ser o assinalados prontamente se alguma instru o da r
15. namespace std Calcula e devolve o m ximo divisor comum de dois inteiros positivos passados como argumentos Opre PC 0 lt mad lt n post CO mdc mdc m n Assume se que m e n n o mudam de valor int mdc int m int n int k if m lt an k m else k n while m k 0 or n k 0 k Escreve no ecr uma frac o no formato usual que lhe passada na forma de dois argumentos inteiros positivos Opre PC YV ouseja nenhuma pr condi o post CO oecr cont m n d emque n e d s oosvaloresde n e d representados em base decimal void escreveFrac o int n int d cout lt lt n lt lt lt lt d Calcula e escreve a soma em termos m nimos de duas frac es positivas lidas do teclado int main Leitura das frac es do teclado cout lt lt Introduza duas frac es ant nl Aii n 2ds cin gt gt nl SDd S n2 SS d2 int k mdc n1 dl nl k dl k k mdc n2 d2 n2 k d2 k 3 2 FUN ES E PROCEDIMENTOS ROTINAS 87 C lculo da frac o soma em termos m nimos int n nl d2 n al int d dl a2 k mdc n d n k d k Escrita do resultado cout lt lt A soma de escreveFrac o n1 d1 cout lt lt com escreveFrac o n2 d2 COUT LA Tg T escreveFrac o n d cout lt lt lt lt endl necess rio portanto definir um procedimento que reduza uma frac o
16. passada como ar gumento na forma de dois inteiros numerador e denominador N o poss vel escrever uma fun o para este efeito pois seriam necess rias duas sa das ou dois valores de devolu o o que as fun es em C n o permitem Assim sendo usa se um procedimento que tem de ser capaz de afectar os valores dos argumentos Ou seja usa se passagem de argumentos por refer ncia O procedimento ent o Reduz a frac o passada com argumento na forma de dois inteiros positivos pre PC n n d d4dA0 lt n 0 lt d post CO E 5 Amde n d 1 void reduzFrac o int amp n int amp d int const k mdc n d n k d k Note se que se usaram as vari veis matem ticas n e d para representar os valores iniciais das vari veis do programa n e d O programa completo ent o include lt iostream gt using namespace std Calcula e devolve o m ximo divisor comum de dois inteiros positivos passados como argumentos 88 CAP TULO 3 MODULARIZA O ROTINAS Opre PC 0 lt mad lt n post CO mdc mdc m n Assume se que m e n n o mudam de valor int mdc int m int n Int ke if m lt n k m else k n while m k 0 or n k 0 gs Reduz a frac o passada com argumento na forma de dois inteiros positivos Opre PC n nAd dA0 lt nAad lt d Opost CO 3 2 Amde n d 1 void reduzFrac o int amp n int amp d int const k mdc n d
17. some convenientemente frac es ne gativas para o que foi apenas necess rio alterar o procedimento reduzFrac o de modo a garantir que o denominador sempre positivo finclude lt iostream gt using namespace std Reduz a frac o passada com argumento na forma de dois inteiros positivos Opre PC n n d d d 0 post CO TA0 lt dAmde n d 1 void reduzFrac o int amp n int amp d Escreve no ecr uma frac o no formato usual que lhe passada na forma de dois argumentos inteiros positivos pre PC V ou seja nenhuma pr condi o post CO o ecr cont m n d emque n e d s oosvaloresde n e d representados em base decimal void escreveFrac o int n int d Calcula e devolve o m ximo divisor comum de dois inteiros passados como argumentos o segundo inteiro tem de ser positivo Opre PC m mAn nA0 lt n post CO mdc mde m n int mdc int m int n Calcula e escreve a soma em termos m nimos de duas frac es lidas do teclado os denominadores n o podem ser nulos int main Leitura das frac es do teclado cout lt lt Introduza duas frac es int nl dl n2 d2 cin gt gt ni gt gt dl gt gt n2 gt gt d2 reduzFrac o nl dl reduzFrac o n2 d2 C lculo da frac o soma em termos m nimos int n ni d2 n2 di int d d1 d2 reduzFrac o n d 114 CAP TULO 3 MODULARIZA O ROTINAS E
18. 1 d2 n2 d1 81 que excede em muito a gama dos int com 6 bits O resultado desastroso N o poss vel evitar totalmente este problema mas poss vel minimiz lo se se reduzir a termos m nimos as frac es de entrada logo ap s a sua leitura Se isso acontecesse como em termos m nimos Z a express o n1 d2 n2 dl teria o valor 27 dentro da gama de valores hipot tica dos int Nos ambientes t picos os valores do tipo int s o representados por 32 bits pelo que o pro blema acima s se p e para numeradores e denominadores muito maiores Mas n o pelo facto de ser um problema mais raro que deixa de ser problema pelo que conv m alterar o programa para tinclude lt iostream gt using namespace std 3 2 FUN ES E PROCEDIMENTOS ROTINAS 69 Calcula e escreve a soma em termos m nimos de duas frac es positivas lidas do teclado int main Leitura das frac es do teclado cout lt lt Introduza duas frac es int n dl n2 d2 en gt gt al gt gt dl gt gt n2 2 gt gt d2 int k mdc nl dl nl k dl k int k mdc n2 d2 n2 k d2 k C lculo da frac o soma em termos m nimos int n nIl d2 n2 al int d d1 d2 int k mdc n d n k d k Escrita do resultado cout lt lt A soma de escreveFfrac o nl d1 cout lt lt com Ty escreveFrac o n2 d2 cout lt lt e escreveFfrac o n
19. 91 using namespace std double const pi 3 1416 Devolve o per metro de uma circunfer ncia de raio r pre PC 0 lt raio post CO per metro 2 xr x raio double per metro double raio return 2 0 pi raio int main cout lt lt Introduza dois raios double raiol raio2 cin gt gt raiol gt gt raio2 Ordena o dos raios por ordem crescente if raiol lt raio2 double const aux raiol raiol raio2 raio2 aux Escrita do resultado cout lt lt raio lt lt raiol lt lt per metro lt lt per metro raiol lt lt endl lt lt raio lt lt raio2 lt lt per metro lt lt per metro raio2 lt lt endl Neste c digo 1 A constante pi vis vel desde a sua defini o at ao final do corpo da fun o main 2 O par metro raio que uma vari vel local a per metro vis vel em todo o corpo da fun o per metro 3 As vari veis raiol e raio2 s o vis veis desde o ponto de defini o antes da opera o de extrac o at ao final do corpo da fun o main 4 A constante aux vis vel desde o ponto de defini o at ao fim da instru o composta controlada pelo if Quanto mais estreito for o mbito de visibilidade de uma vari vel menores os danos causados por poss veis utiliza es err neas Assim as vari veis locais devem definir se tanto quanto poss vel imediatamente ante
20. Cap tulo 3 Modulariza o rotinas Methods are more important than facts Donald E Knuth Selected Papers in Computer Science 176 1996 A modulariza o um conceito extremamente importante em programa o Neste cap tulo abordar se o n vel at mico de modulariza o as fun es e os procedimentos Este tipo de modulariza o fundamental em programa o procedimental Quando se come ar a abordar a programa o baseada em objectos no Cap tulo 7 falar se de um outro n vel de modu lariza o as classes Finalmente a modulariza o regressar a um n vel ainda mais alto no Cap tulo 9 3 1 Introdu o modulariza o Exemplos de modulariza o i e exemplos de sistemas constitu dos por m dulos s o bem conhecidos A maior parte dos bons sistemas de alta fidelidade s o compostos por m dulos o amplificador o equalizador o leitor de DVD o sintonizador as colunas etc Para o produtor de um sistema deste tipo a modulariza o tem v rias vantagens 1 reduz a complexidade do sistema pois cada m dulo mais simples que o sistema na globalidade e pode ser desenvolvido por um equipa especializada 2 permite alterar um m dulo independentemente dos outros por exemplo porque se de senvolveu um novo circuito para o amplificador melhorando assim o comportamento do sistema na totalidade 3 facilita a assist ncia t cnica pois f cil verificar qual o m dulo respons vel pela avaria e
21. INAS while m 0 int const auxiliar n m n m m auxiliar o o assert m k 0 and n k 0 return n int main int m 5 1 mdc m 3 6 2A int divisor 2B cout lt lt divisor lt lt endl 3 em que se dividiu a instru o 2 em duas sub instru es 2A e 2B Considera se para simplificar que pilha est vazia quando se come a a executar a fun o main topo da aa De seguida executada a instru o 1 que constr i a vari vel m Como essa vari vel autom tica constru da na pilha que fica m int ZA Que acontece quando a instru o 2A executada A chamada da fun o mdc na instru o 2A come a por guardar na pilha o endere o da instru o a executar quando a fun o retornar i e 2B 3 4 MECANISMO DE INVOCA O DE ROTINAS 119 retorno a2B m int 5 GU Em seguida s o constru dos na pilha os par metros da fun o Cada par metro inicializado com o valor do argumento respectivo n int m int retorno a2B m int 5 ZA Neste momento existem na pilha duas vari veis de nome m uma pertencente fun o main e outra fun o mdc f cil saber em cada instante quais s o as vari veis autom tica vis veis s o todas as vari veis desde o topo da pilha at ao pr ximo endere o de retorno Isto neste momen
22. NAS 63 A este ltimo tipo de programa o chama se programa o centrada nos dados e a base da programa o baseada em objectos e consequentemente da programa o orientada para ob jectos 3 2 1 Abordagens descendente e ascendente Nos cap tulos anteriores introduziram se v rios conceitos como os de algoritmos dados e programas Explicaram se tamb m algumas das ferramentas das linguagens de programa o tais como vari veis constantes tipos valores literais express es opera es etc Mas como usar todos estes conceitos para resolver um problema em particular Existem muitas poss veis abordagens resolu o de problemas em programa o quase todas com um paralelo perfeito com as abordagens que se usam no dia a dia Porventura uma das abordagens mais cl ssicas em programa o a abordagem descendente ou top down Abordar um problema de cima para baixo corresponde a olhar para ele na globalidade e identificar o mais pequeno n mero de sub problemas independentes poss vel Depois sendo esses sub problemas independentes podem se resolver independentemente usando a mesma abordagem cada sub problema dividido num conjunto de sub sub problemas mais sim ples Esta abordagem tem a vantagem de limitar a quantidade de informa o a processar pelo programador em cada passo e de por divis o sucessiva ir reduzindo a complexidade dos problema at trivialidade Quando os problemas identificados se tornam t
23. Na pr tica conveniente faz lo para mostrar claramente ao leitor o significado das entradas da fun o A sintaxe das declara es em sentido estrito simples o cabe alho da rotina como na defini o mas seguido de em vez do corpo O facto de uma rotina estar declarada n o a dispensa de ter de ser definida mais cedo ou mais tarde todas as rotinas t m de estar definidas em algum lado Por outro lado uma defini o um vez que cont m o cabe alho da rotina tam b m serve de declara o Assim ap s uma defini o as declara es em sentido estrito s o desnecess rias Note se que mesmo que j se tenha procedido declara o pr via de uma rotina necess rio voltar a incluir o cabe alho na defini o O facto de uma defini o ser tamb m uma declara o foi usado no programa da soma de frac es para colocando as defini es das rotinas antes da fun o main permitir que elas fossem usadas no corpo da fun o main poss vel inverter a ordem das defini es atrav s de declara es pr vias finclude lt iostream gt using namespace std Calcula e escreve a soma em termos m nimos de duas frac es positivas lidas do teclado int main Declara o dos procedimentos necess rios Estas declara es s o vis veis apenas dentro da fun o main void reduzFrac o int amp n int amp d void escreveFrac o int n int d Leitura das frac es do te
24. ZA O ROTINAS procedimento que n o devolve qualquer valor Alternativamente poder se ia usar return O que acontece ao se invocar este procedimento como indicado na segunda linha do seguinte c digo int a 1 b 2 troca a b A invoca o n o ocorre dentro de qualquer express o dado que o procedi mento n o devolve qualquer valor cout lt lt a lt lt T lt lt b lt lt endl 1 S o constru das as vari veis x e y 2 Sendo par metros do procedimento a vari vel x inicializada com o valor 1 valor de a e a vari vel y inicializada com o valor 2 valor de b Assim os par metros s o c pias dos argumentos 3 Durante a execu o do procedimento os valores guardados em x e y s o trocados ver Figura 8 1 4 Antes de o procedimento terminar as vari veis x e y t m valores 2 e 1 respectivamente 5 Quando termina a execu o do procedimento as vari veis x e y s o destru das ver explica o mais frente Ou seja n o h qualquer efeito sobre os valores das vari veis a e b Os par metros mudaram de valor dentro do procedimento mas as vari veis a e b n o mudaram de valor a continua a con terleba conter 2 Este tipo de comportamento ocorre quando numa fun o ou procedimento se usa a chamada passagem de argumentos por valor Normalmente este um comportamento desej vel S em alguns casos como neste exemplo esta uma caracter stica indesej vel
25. a nenhuma pr condi o post CO m nimo anNa lt hb vV m nimo bAb lt a int m nimo int a int D Calcula e escreve a soma em termos m nimos de duas frac es positivas lidas do teclado int main Leitura das frac es do teclado cout lt lt Introduza duas frac es inedi Alz A2 d2y cin gt gt ni gt gt dl gt gt n2 gt gt gt d2 reduzFrac o nl dl reduzFrac o n2 d2 C lculo da frac o soma em termos m nimos int n nl d2 n2 al int d dl a2 reduzFrac o n d 3 2 FUN ES E PROCEDIMENTOS ROTINAS 107 Escrita do resultado cout lt lt A soma de escreveFfrac o nl d1 cout lt lt com T escreveFrac o n2 d2 cout lt lt on escreveFrac o n d E lt lt lt lt endl cou void reduzFrac o int amp n int amp d assert 0 lt n and 0 lt d int const k mdc n d n k d k void escreveFrac o int const n int const d cout lt lt n lt lt lt lt d int mdc int const m int const n assert 0 lt m and O lt n int k m nimo m n while m k 0 orn amp k 0 int m nimo int const a int const b if a lt b return a else return b Que h de errado com este programa Considere se o que acontece se o seu utilizador intro 108 CAP TULO 3 MODULARIZA O ROTINAS duzir frac es negativas por exemplo
26. a a fun o mdc com argumentos 0 e 10 por exemplo Nesse caso o valor inicial de k 0 o que leva a que a condi o da instru o iterativa while tente calcular uma divis o por zero Logo que isso sucede o programa aborta com uma mensagem de erro pouco simp tica e semelhante seguinte Floating exception core dumped Existe uma forma padronizada de explicitar as condi es que devem ser verdadeiras nos v rios locais de um programa obrigando o computador a verificar a sua validade durante a execu o do programa as chamadas instru es de asser o afirma o Para se poder usar instru es de asser o tem de ser incluir o ficheiro de interface apropriado finclude lt cassert gt 104 CAP TULO 3 MODULARIZA O ROTINAS As instru es de asser o t m o formato assert condi o onde condi o uma condi o que deve ser verdadeira no local onde a instru o se encontra para que o programa se possa considerar correcto Se a condi o for verdadeira quando a instru o de asser o executada nada acontece a instru o n o tem qualquer efeito Mas se a condi o for falsa o programa aborta e mostrada uma mensagem de erro com o seguinte aspecto ficheiro execut vel ficheiro fonte linha cabe alho Assertion condi o failed onde ficheiro execut vel Nome do ficheiro execut vel onde ocorreu o erro ficheiro fonte Nome do ficheiro em linguagem C onde ocorreu o erro linha
27. a par metro representado por um par tipo nome sendo os pares separados por v rgulas Isto tipo de devolu o nome lista de par metros O cabe alho de uma rotina corresponde sua interface tal como as tomadas para cabos nas traseiras de um amplificador e os bot es de controlo no seu painel frontal constituem a sua interface Quando a rotina uma fun o porque calcula um valor de um determinado tipo Esse tipo indicado em primeiro lugar no cabe alho No caso de um procedimento que n o calcula nada necess rio colocar a palavra chave void no lugar desse tipo como se ver mais frente Logo a seguir indica se o nome da rotina e finalmente uma lista de par metros que consiste simplesmente numa lista de defini es de vari veis com uma sintaxe semelhante embora n o id ntica que se viu no Cap tulo 2 No exemplo anterior definiu se uma fun o que tem dois par metros ambos do tipo int e que devolve um valor inteiro O seu cabe alho int mdc int m int n A sintaxe de especifica o dos par metros diferente da sintaxe de defini o de vari veis normais pois n o se podem definir v rios par metros do mesmo tipo separando os seus nomes por v rgulas o cabe alho 74 int mdc int m inv lido pois falta lhe a especifica o do tipo do par metro n n CAP TULO 3 MODULARIZA O ROTINAS O corpo desta fun o i e a sua implementa o corresponde s instr
28. a se que est o definidas as fun es int soma int const a int const b return a b int soma int const a int const b int const c return a b c float soma float const a float const b return a b double soma double const a double const b return a b Ao executar as instru es ineril 22 float flp f2 double d1 d2 i2 soma il 4 invoca int soma int int i2 soma il 3 i2 invoca int soma int int int f2 soma 5 6 f fl invoca float soma float float d2 soma dl 10 0 invoca double soma double double s o chamadas as fun es apropriadas para cada tipo de argumentos usados Este tipo de comportamento emula para as fun es definidas pelo programador o comportamento normal dos operadores do C A opera o por exemplo significa soma de int se os operandos forem int significa soma de float se os operandos forem float etc O exemplo mais claro talvez seja o do operador divis o As instru es HA no o de assinatura usual um pouco mais completa que na linguagem C pois inclui o tipo de devolu o Na linguagem C o tipo de devolu o n o faz parte da assinatura 126 CAP TULO 3 MODULARIZA O ROTINAS cout lt lt 1 2 lt lt endl cout lt lt 1 0 2 0 lt lt endl t m como resultado no ecr porque no primeiro caso sendo os operandos inteiros a divis o usada a divis o inteira As sim cada ope
29. al a fun o m dulo e qual a sua interface utiliza o de um sistema em que se olha para ele apenas do ponto de vista do seu fun cionamento externo chama se abstrac o A capacidade de abstrac o das qualidades mais importantes que um programador pode ter ou desenvolver pois permite lhe reduzir subs tancialmente a complexidade da informa o que tem de ter presente na mem ria conduzindo por isso a substanciais ganhos de produtividade e a uma menor taxa de erros A capacidade de abstrac o t o fundamental na programa o como no dia a dia Ningu m conduz o autom vel com a preocupa o de saber se a vela do primeiro cilindro produzir a fa sca no momento certo para a pr xima explos o Um autom vel para o condutor normal um objecto que lhe permite deslocar se e que possui um interface simples a igni o para ligar o autom vel o volante para ajustar a direc o o acelerador para ganhar velocidade etc O encapsulamento dos m dulos ao esconder do consumidor o seu mecanismo facilita lhe esta vis o externa dos m dulos e portanto facilita a sua capacidade de abstrac o D se o nome de c digo a qualquer peda o de programa numa dada linguagem de programa o 62 CAP TULO 3 MODULARIZA O ROTINAS 3 2 Fun es e procedimentos rotinas A modulariza o na realidade um processo hier rquico muito provavelmente cada m dulo de um sistema de alta fidelidade composto por sub m dulos razoavel
30. ando o fluxo de execu o atinge uma instru o de retorno As instru es de retorno consistem na palavra chave return seguida de uma express o e de um A express o tem de ser de um tipo compat vel com o tipo de devolu o da fun o O resultado da express o depois de convertido no tipo de devolu o o valor devolvido ou calculado pela fun o No caso da fun o mdc o retorno e a devolu o fazem se com a instru o return k O valor devolvido neste caso o valor contido na vari vel k que o mdc dos valores iniciais demen 3 2 10 Significado de void Um procedimento tem a mesma sintaxe de uma fun o mas n o devolve qualquer valor Esse facto indicado usando a palavra chave void como tipo do valor de devolu o Um pro cedimento termina quando se atinge a chaveta final do seu corpo ou quando se atinge uma instru o de retorno simples sem qualquer express o i e return Os procedimentos t m tipicamente efeitos laterais e g afectam valores de vari veis que lhes s o exteriores e g usando passagem de argumentos por refer ncia descrita na pr xima sec o Assim sendo para evitar maus comportamentos n o se devem usar procedimentos em express es ver Sec o 2 7 8 A utiliza o do tipo de devolu o void impede a chamada de procedimentos em express es pelo que o seu uso recomendado q Resumindo de toda a conveni ncia que os procedimentos tenham tipo
31. clado cout lt lt Introduza duas frac es into nl dt n2 d2 cin gt gt nico gt dl gt gt n2 gt gt d2 reduzFrac o nl dl reduzFrac o n2 d2 C lculo da frac o soma em termos m nimos int n nl da2 n al int d d1 d2 reduzFrac o n d Escrita do resultado cout lt lt A soma de escreveFfrac o nl d1 cout lt lt come escreveFrac o n2 d2 3 2 FUN ES E PROCEDIMENTOS ROTINAS 97 cout lt lt mM escreveFfrac o n d cout lt lt lt lt endl Reduz a frac o passada com argumento na forma de dois inteiros positivos Opre PC n nAd dA0Q lt nAd lt d Opost CO 3 2 Amde n d 1 void reduzFrac o int amp n int amp d Declara o da fun o necess ria Esta declara o vis vel apenas dentro desta fun o int mdc int m int n int const k mdc n d n k d k Escreve no ecr uma frac o no formato usual que lhe passada na forma de dois argumentos inteiros positivos pre PC V ou seja nenhuma pr condi o post CO o ecr cont m n d emque n e d s oosvaloresde n e d representados em base decimal void escreveFrac o int n int d cout lt lt n lt lt lt lt d Calcula e devolve o m ximo divisor comum de dois inteiros positivos passados como argumentos pre PC 0 lt mA0 lt n post CO mdc mdc m n Assume se que m e n n o mudam de
32. cula e escreve a soma em termos m nimos de duas frac es positivas lidas do teclado int main 68 CAP TULO 3 MODULARIZA O ROTINAS Leitura das frac es do teclado cout lt lt Introduza duas frac es int nl dl n2 d2 cin gt gt nl gt gt di gt gt n2 gt gt d2 C lculo da frac o soma em termos m nimos int n nl d2 2 dil int d di d2 int k mdc n d n k omesmoque n n k d k o mesmo que d d k Escrita do resultado cout lt lt A soma de escreveFrac o n1 d1 cout lt lt com y escreveFrac o n2 d2 cout lt lt Mi escreveFfrac o n d cout lt lt lt lt endl Neste caso adiou se mais um problema admitiu se que est dispon vel algures uma fun o chamada mdc que calcula o mdc de dois inteiros Isto significa que mais tarde ser preciso definir esse procedimento Recorda se no entanto que o algoritmo para o c lculo do mdc foi visto no Cap tulo 1 e revisto no Cap tulo 2 A solu o encontrada ainda precisa de ser refinada Suponha se que o programa compilado e executado num ambiente onde valores do tipo int s o representados com apenas 6 bits Nesse caso de acordo com a discuss o do cap tulo anterior essas vari veis podem conter valores entre 32 e 31 Que acontece quando sendo as frac es de entrada e 5 se inicializa a vari vel n O valor da express o n
33. de devolu o void e que as fun es se limitem a devolver um valor calculado e n o tenham qualquer efeito lateral O respeito por esta regra simples pode poupar muitas dores de cabe a ao programador No programa da soma de frac es ficou em falta a defini o do procedimento escreveF rac o A sua defini o muito simples Isto uma simplifica o Na realidade podem haver express es envolvendo operandos do tipo void Mas a sua utilidade muito restrita 80 CAP TULO 3 MODULARIZA O ROTINAS Escreve no ecr uma frac o no formato usual que lhe passada na forma de dois argumentos inteiros positivos pre PC YV ouseja nenhuma pr condi o post CO oecr cont m n d emque n e d s oosvaloresde n e d representados em base decimal void escreveFrac o int n int d cout lt S n SKi E qa d N o necess ria qualquer instru o de retorno pois o procedimento retorna quando a execu o atinge a chaveta final O programa completo ent o include lt iostream gt using namespace std Calcula e devolve o m ximo divisor comum de dois inteiros positivos passados como argumentos pre PC 0 lt mA0 lt n post CO mdc mdc m n Assume se que m e n n o mudam de valor int mdc int m int n Int k if m lt n k m else k n while m k 0 or n k 0 gs Escreve no ecr uma frac o no formato usual que lhe passada na for
34. decimal void escreveFrac o int n int d Calcula e devolve o m ximo divisor comum de dois inteiros positivos passados como argumentos Opre PC 0 lt mAa0 lt n post CO mdc mde m n int mdc int m int n Devolve o menor de dois inteiros passados como argumentos Opre PC V ouseja nenhuma pr condi o post CO m nimo anNa lt hb V m nimo bAb lt a int m nimo int a int b Calcula e escreve a soma em termos m nimos de duas frac es positivas lidas do teclado int main Leitura das frac es do teclado cout lt lt Introduza duas frac es inteni dl n2p d2s in gt gt nl gt gt dl gt 5 gt n2 gt gt d2s 3 2 FUN ES E PROCEDIMENTOS ROTINAS 101 reduzFrac o nl dl reduzFrac o n2 d2 C lculo da frac o soma em termos m nimos intem Fog 2n dl int d dl a2 reduzFrac o n d Escrita do resultado cout lt lt A soma de escreveFfrac o nl d1 cout lt lt com escreveFrac o n2 d2 COUT LA No dt escreveFrac o n d cout lt lt to lt lt endis void reduzFrac o int amp n int amp d int const k mdc n d m k d k void escreveFrac o int const n int const d cout lt lt n lt lt lt lt d int mdc int const m int const n int k m nimo m n while m k 0 orn amp k 0 k int m nimo int const a int co
35. dos por s o coment rios de linha Este coment rio cont m e uma descri o do que a fun o calcula ou do que o procedimento faz em portugu s vern culo e a pr condi o ou PC da rotina ou seja a condi o que as entradas i e os valores iniciais dos par metros t m de verificar de modo a assegurar o bom funcionamento da rotina e e a condi o objectivo ou CO mais importante ainda que a PC que indica a condi o que deve ser v lida quando a rotina termina numa instru o de retorno No caso de uma fun o o seu nome pode ser usado na condi o objectivo para indicar o valor devolvido no seu final Na defini o acima colocou se o coment rio junto ao cabe alho da rotina por ser fundamental para se perceber o que a rotina faz ou calcula O cabe alho de uma rotina por si s n o diz o que ela faz simplesmente como se utiliza Por outro lado o corpo de uma rotina diz como funciona Uma rotina uma caixa preta no seu interior fica o mecanismo o corpo da rotina no exterior a interface o cabe alho da rotina e pode se ainda saber para que serve e como se utiliza lendo o seu manual de utiliza o os coment rios contendo a descri o em portugu s e a pr condi o e a condi o objectivo Estes coment rios s o parte da documenta o do programa Os coment rios de bloco come a dos por e os de linha come ados por s o considerados coment rios de documenta o por alguns sistemas
36. e de escolher o que a rotina faz nessas circuns t ncias Pode fazer o que entender desde devolver lixo no caso de uma fun o a apagar o disco r gido e escrever uma mensagem perversa no ecr tudo v lido Claro est que isso n o desej vel O ideal seria que se uma pr condi o ou uma condi o objectivo falhassem esse erro fosse assinalado claramente No Cap tulo 14 ver se que o mecanismo das excep es o mais adequado para lidar com este tipo de situa es Para j falta de melhor optar se por abortar imediatamente a execu o do programa escrevendo se uma mensagem de erro apropriada no ecr Considere se de novo a fun o para c lculo do m ximo divisor comum Calcula e devolve o m ximo divisor comum de dois inteiros positivos passados como argumentos Opre PC 0 lt mad lt n post CO mdc mde m n int mdc int const m int const n 3 2 FUN ES E PROCEDIMENTOS ROTINAS 103 int k m nimo m n while m k 0 orn amp k 0 k Que sucede se a pr condi o for violada Suponha se que a fun o invocada com argumen tos 10 e 6 Ent o a vari vel k ser inicializada com o valor 6 A guarda do ciclo inicialmente verdadeira pelo que o valor de k passa para 7 Para este valor de k a guarda ser tamb m ver dadeira E s lo tamb m para 8 etc Tem se portanto um ciclo infinito N o exactamente Como se viu no Cap tulo 2 as vari
37. e relevante do correspondente programa int m int n Como inicializar m e n int k if m lt n k m else k n while m 5 k 0 orn k 0 3 2 FUN ES E PROCEDIMENTOS ROTINAS 71 Este tro o de programa calcula o mdc dos valores de m e n e coloca o resultado na vari vel k necess rio colocar este c digo numa fun o ou seja num m dulo com uma interface e uma implementa o escondida numa caixa Come a se por colocar o c digo numa caixa i e entre int m int n Como inicializar m e n int k if m lt A k m else k n while m k 0 or n amp k 0 k Tudo o que fica dentro da caixa est inacess vel do exterior E necess rio agora atribuir um nome ao m dulo tal como se atribui o nome Amplificador ao m dulo de uma aparelhagem que amplifica os sinais udio vindos de outros m dulos Neste caso o m dulo chama se mdc mdc int m int n Como inicializar m e n int k if m lt n k m else k n while m 5 k 0 or n k 0 k Qual a interface deste m dulo ou melhor desta fun o Uma caixa sem interface in til A fun o deve calcular o mdc de dois n meros Mas de onde v m eles O resultado da fun o fica guardado na vari vel k que est dentro da caixa Como comunicar esse valor para o exterior No programa da soma de frac es a fun o mdc utilizada ou melhor invocada ou ai
38. evolve o m ximo divisor comum de dois inteiros positivos passados como argumentos Opre PC 0 lt ma0 lt n post CO mdc mde m n int mdc int const m int const n assert 0 lt n and 0 lt d int k m nimo m n while m 5 k 0 orn k 0 k assert k mdc m n absurdo return k Porqu Simplesmente porque isso implica uma invoca o recursiva intermin vel fun o ver Sec o 3 3 Isso significa que se dever exprimir a condi o objectivo numa forma menos compacta CO m mde 0An mdc 0A Qj j mdec lt j m 74 0Vn 7 0 Os dois primeiros termos da condi o objectivo t m tradu o directa para C Mas o segundo recorre a um quantificador que significa qualquer que seja j maior que o valor devolvido pela fun o esse j n o pode ser divisor comum de m e n os quantificadores ser o abordados mais tarde N o h nenhuma forma simples de escrever uma instru o de asser o recorrendo a quantificadores excepto invocando uma fun o que use um ciclo para verificar o valor do quantificador Mas essa solu o al m de complicada obriga implementa o de uma fun o adicional cuja condi o objectivo recorre de novo ao quantificador Ou seja n o solu o Assim o melhor que se pode fazer reter os dois primeiros termos da condi o objectivo reescrita Calcula e devolve o m ximo divisor comum de dois inteiros positivos passados como argumentos O
39. fini o de uma rotina nica e indica a sua interface i e como a rotina se utiliza e que nome tem e a sua implementa o i e como funciona Uma invoca o de uma rotina feita onde quer que seja necess rio recorrer aos seus servi os para calcular algo no caso de uma fun o ou para fazer alguma coisa no caso de um procedimento Finalmente falte definir como se fazem as sa das da fun o Uma fun o em C s pode ter uma sa da Neste caso a sa da o valor guardado em k no final da fun o que o maior divisor comum dos dois par metros m e n Para que o valor de k seja usado como sa da da fun o usa se uma instru o de retorno mdc int m int n int k if m lt n k m else k n while m 5 k 0 or n k 0 3 2 FUN ES E PROCEDIMENTOS ROTINAS 73 return k A defini o da fun o tem de indicar claramente que a fun o tem uma sa da de um dado tipo Neste caso a sa da um valor do tipo int pelo que a defini o da fun o fica int mdc int m int n int k if m lt n k m else k n while m 5 k 0 or n k 0 k return k 3 2 3 Sintaxe das defini es de fun es A defini o de uma rotina constitu da por um cabe alho seguido de um corpo que consiste no conjunto de instru es entre No cabe alho s o indicados o tipo do valor calculado ou devolvido por essa rotina o nome da rotina e a sua lista de par metros cad
40. idente que mais tarde ser preciso definir esse procedimento que usando um pouco de abordagem ascendente se percebeu vir a ser utilizado em tr s locais diferentes Podia se ter levado a abordagem ascen dente mais longe se se vai lidar com frac es n o seria til um procedimento para ler uma frac o do teclado E uma outra para reduzir uma frac o a termos m nimos O resultado obtido como uma tal abordagem dada a pequenez do problema seria semelhante ao que se obter prosseguindo a abordagem descendente Sobrou outro problema como escrever a frac o resultado sem saber onde se encontram o seu numerador e o seu denominador Claramente necess rio para a resolu o do sub problema do c lculo da soma definir duas vari veis adicionais onde esses valores ser o guardados include lt iostream gt using namespace std Calcula e escreve a soma em termos m nimos de duas frac es positivas lidas do teclado int main Leitura das frac es do teclado cout lt lt Introduza duas frac es ine no dU gt 25 d2s cin gt gt nl gt gt dl gt gt n2 gt gt d2 C lculo da frac o soma em termos m nimos int n int d Escrita do resultado cout lt lt A soma de escreveFfrac o nl d1 cout lt lt com s escreveFrac o n2 d2 cout lt lt T mM escreveFfrac o n d cout lt lt lt lt endl necess rio agora resol
41. int n int 3 3 3 3 3 zint 6 retorno retorno retorno retorno retorno a 4B a 4B a 4B a 4B a 4B MM MAMMA a b Q a e 8 h Figura 3 3 Evolu o da pilha durante invoca es recursivas da fun o factorial Admite se que a pilha inicialmente est vazia como indicado em a 124 CAP TULO 3 MODULARIZA O ROTINAS Neste momento existem duas vers es da constante n na pilha uma por cada chamada fun o que ainda n o terminou h uma chamada principal e outra aninhada E esta repeti o das vari veis e constantes locais que permite s fun es recursivas funcionarem sem proble mas A execu o passa ent o para o in cio da fun o instru o 1 De novo como constante n da chamada em execu o correntemente 2 e portanto diferente de O e de 1 executada a instru o ap s o i f que a instru o 3A Mas a instru o 3A consiste numa nova chamada fun o pelo que os passos acima se repetem mas sendo agora o par metro inicializado com o valor do argumento i e 1 e sendo o endere o de retorno 3B resultando na pilha indicada em d na Figura 3 3 A execu o passa ent o para o in cio da fun o instru o 1 Agora como a constante n da chamada em execu o correntemente 1 executada a instru o condicionada pelo if que a instru o 2 Mas a instru o 2 consiste numa instru o de ret
42. interna de cada m dulo No caso de um bom sistema de alta fidelidade tal corresponde a minimizar a complexidade dos cabos entre os m dulos e a garantir que os m dulos cont m apenas os circuitos que contribuem para a fun o do m dulo A coes o tem portanto a ver com as liga es internas a um m dulo que idealmente devem ser maximizadas Normalmente um m dulo s pode ser coeso se tiver uma nica fun o bem definida H algumas restri es adicionais a impor a uma boa modulariza o N o basta que um m dulo tenha uma fun o bem definida tem de ter tamb m uma interface bem definida Por interface entende se aquela parte de um m dulo que est acess vel do exterior e que permite a sua utiliza o claro por exemplo que um dono de uma alta fidelidade n o pode substituir o seu amplificador por um novo modelo se este tiver liga es e cabos que n o sejam compat veis com o modelo mais antigo A interface de um m dulo a parte que est acess vel ao consumidor Tudo o resto faz parte da sua implementa o ou mecanismo e t pico que esteja encerrado numa caixa fora da vista ou pelo menos fora do alcance do consumidor Num sistema bem desenhado cada m dulo mostra a sua interface e esconde a complexidade da sua implementa o cada m dulo est encapsulado numa caixa a que se costuma chamar uma caixa preta Por exemplo num rel gio v se o mostrador os ponteiros e o man pulo para acertar as ho
43. ito til na resolu o de alguns problemas mas deve ser usado com cautela A chamada de uma rotina recursivamente implica que as vari veis locais par metros inclu dos s o constru das tantas vezes quantas a rotina chamada e s s o destru das quando as correspondentes chamadas retornam Como as chamadas recursivas se aninham umas dentro das outras se ocorrerem muitas chamadas recursivas n o s pode ser necess ria muita mem ria para as v rias vers es das vari veis locais uma vers o por cada chamada ani nhada como tamb m a execu o pode tornar se bastante lenta pois a chamada de fun es implica alguma perda de tempo nas tarefas de arruma o da casa do processador A fun o factorial em particular pode ser implementada usando um ciclo que resulta em c digo muito mais eficiente e claro Devolve o factorial do inteiro passado como argumento Opre PC 0 lt n post CO factorial n ou ainda factorial 2 5 Zi int factorial int const n int factorial 1 for int i 0 i n i factorial i 1 return factorial poss vel ainda que a recursividade seja entre duas ou mais rotinas que se chamam mutuamente P q J q 116 CAP TULO 3 MODULARIZA O ROTINAS Muito importante tamb m a garantia de que uma rotina recursiva termina sempre A fun o factorial recursiva acima tem problemas graves quando invocada com um argumento nega tivo que vai sendo cha
44. k men 7 A execu o do programa passa para a instru o seguinte de invoca o da fun o neste caso 3B Instru o 3B atribu do vari vel divisor o valor calculado pela fun o neste caso 2 Diz se que a fun o devolveu o valor calculado Instru o 4 O valor de divisor escrito no ecr 3 2 7 Par metros Par metros s o as vari veis listadas entre par nteses no cabe alho da defini o de uma rotina S o vari veis locais ver Sec o 3 2 12 embora com uma particularidade s o automatica mente inicializadas com o valor dos argumentos respectivos em cada invoca o da rotina 3 2 FUN ES E PROCEDIMENTOS ROTINAS 79 3 2 8 Argumentos Argumentos s o as express es listadas entre par nteses numa invoca o ou chamada de uma rotina O seu valor utilizado para inicializar os par metros da rotina invocada 3 2 9 Retorno e devolu o Em ingl s a palavra return tem dois significados distintos retornar ou regressar e devolver O portugu s neste caso mais rico pelo que se usar o palavras distintas dir se que uma rotina retorna quando termina a sua execu o e o fluxo de execu o regressa ao ponto de invoca o e dir se que uma fun o ao retornar devolve um valor que pode ser usado na express o em que a fun o foi invocada No exemplo do mdc acima o valor inteiro devolvido usado numa express o envolvendo o operador de atribui o Uma fun o termina qu
45. l int const n assert 0 lt n and n lt 12 if n 0 of n 1 1 return 1 4 2 factorial n 1 3A return n 3B int main factorial 3 4A cout lt lt lt lt endl 4B Que acontece ao ser executada a instru o 4A Essa instru o cont m uma chamada fun o factorial Assim tal como se viu antes as vari veis locais da fun o neste caso apenas o par metro constante n s o colocadas na pilha logo ap s o endere o da instru o a executar quando fun o retornar Quando a execu o passa para a instru o 1 j a pilha est j como indicado em b na Figura 3 3 Em seguida como a constante n cont m 3 e portanto diferente de 0 e de 1 executada a instru o ap s o i f que a instru o 3A se tiver d vidas acerca do funcionamento do if consulte a Sec o 4 1 1 Mas a instru o 3A consiste numa nova chamada fun o pelo que os passos acima se repetem mas sendo agora o par metro inicializado com o valor do argumento i e 2 e sendo o endere o de retorno 3B resultando na pilha indicada em c na Figura 3 3 3 4 MECANISMO DE INVOCA O DE ROTINAS 123 topo da pilha ra n int valor devolvido retorno o mesmo que frozen a 3B z P constante n int n int n int 2 2 2 int 2 retorno retorno retorno a 3B a 3B a 3B n inte n int amp n intg n
46. l2 post CO factorial n ou ainda factorial TIL 5 OA int factorial int const n assert 0 lt n and n lt 12 if n 0 or n 1 return 1 return n factorial n 1 o mesmo acontecendo com a vers o n o recursiva Devolve o factorial do inteiro passado como argumento Opre PC 0 lt n lt l2 post CO factorial n ouainda factorial Ji i int factorial int const n assert 0 lt n and n lt 12 int factorial 1 for int i 0 i n i factorial i 1 return factorial 3 4 MECANISMO DE INVOCA O DE ROTINAS 117 Para se compreender profundamente o funcionamento das rotinas recursivas tem de se com preender o mecanismo de chamada ou invoca o de rotinas que se explica na pr xima sec o 3 4 Mecanismo de invoca o de rotinas Quando nas sec es anteriores se descreveu a chamada da fun o mdc referiu se que os seus par metros eram constru dos no in cio da chamada e destru dos no seu final e que a fun o ao terminar retornava para a instru o imediatamente ap s a instru o de invoca o Como que o processo de invoca o funciona na pr tica Apesar de ser mat ria para a disciplina de Arquitectura de Computadores far se aqui uma descri o breve e simplifi cada do mecanismo de invoca o de rotinas que ser til embora n o fundamental para se compreender o funcionamento das rotinas recursivas O mecanismo de invoca o de rotinas u
47. ma de dois argumentos inteiros positivos pre PC YV ouseja nenhuma pr condi o post CO oecr cont m n d emque n e d s oosvaloresde n e d representados em base decimal void escreveFrac o int n int d cout lt lt n lt lt lt lt d 3 2 FUN ES E PROCEDIMENTOS ROTINAS 81 Calcula e escreve a soma em termos m nimos de duas frac es positivas lidas do teclado int main Leitura das frac es do teclado cout lt lt Introduza duas frac es intentie AL n2 d2 cin gt gt ni gt gt dl gt gt n2 gt gt d2 int k mdc nl dl nl k dl k k mdc n2 d2 n2 k d2 k C lculo da frac o soma em termos m nimos int n nl ada2 n x dI int d d1 d2 k mdc n d n k d k Escrita do resultado cout lt lt A soma de escreveFfrac o nl d1 COUE lt lt com escreveFrac o n2 d2 cout lt lt T Ty escreveFfrac o n d cout lt lt lt lt endl 3 2 11 Passagem de argumentos por valor e por refer ncia Observe o seguinte exemplo de procedimento O seu programador pretendia que o procedi mento trocasse os valores de duas vari veis passadas como argumentos Aten o Este procedimento n o funciona void troca int x int y int const auxiliar x x yi y auxiliar N o h instru o de retorno expl cita pois trata se de um 82 CAP TULO 3 MODULARI
48. mada recursivamente a mesma fun o com valores do argumento cada vez menores mais negativos sem fim vista Podem acontecer duas coisas Como cada chamada da fun o implica a constru o de uma vari vel local o par metro n num espa o de mem ria reservado para a chamada pilha stack como se ver na pr xima sec o esse espa o pode se esgotar o que leva o programa a abortar Ou ent o se por acaso houver muito mas mesmo muito espa o dispon vel na pilha as chamadas recursivas continuar o at se atingir o limite inferior dos inteiros nos argumentos Nessa altura a chamada seguinte feita com o menor dos inteiros menos uma unidade que como se viu no Cap tulo 2 o maior dos intei ros A partir da os argumentos das chamadas recursivas come am a diminuir e ao fim de muito mas mesmo muito tempo atingir o o valor 0 que terminar a sequ ncia de chamadas recursivas sendo devolvido um valor errado Os problemas n o surgem apenas com argumentos negativos na realidade que os valores do factorial crescem depressa pelo que a fun o n o pode ser invocada com argumentos de masiado grandes No caso de os inteiros terem 32 bits o limite a impor aos argumentos que t m de ser inferiores a 13 A fun o deve sofrer uma actualiza o na pr condi o e j agora ser equipada com as instru es de asser o apropriadas Devolve o factorial do inteiro passado como argumento Opre PC 0 lt n lt
49. mente independentes embora invis veis para o consumidor O mesmo se passa na programa o Para j no en tanto abordar se o apenas as unidades at micas de modulariza o em programa o fun es e procedimentos Fun o Conjunto de instru es com interface bem definida que efectua um dado c lculo Procedimento Conjunto de instru es com interface bem definida que faz qualquer coisa Por uma quest o de simplicidade daqui em diante chamar se rotina quer a fun es quer a procedimentos Ou seja a unidade at mica de modulariza o s o as rotinas que se podem ser ou fun es e ou procedimentos As rotinas permitem isolar peda os de c digo com objectivos bem definidos e torn los reuti liz veis onde quer que seja necess rio O fabrico de uma rotina corresponde em C quilo que se designa por defini o Uma vez definida fabricada uma rotina pode ser utilizada sem que se precise de conhecer o seu funcionamento interno da mesma forma que o audi filo n o est muito interessado nos circuitos dentro do amplificador mas simplesmente nas suas caracter sticas vistas do exterior Rotinas s o pois como caixas pretas uma vez definidas e correctas devem ser usadas sem preocupa es quanto ao seu funcionamento interno Qualquer linguagem de programa o e o C em particular fornece um conjunto de tipos b sicos e de opera es que se podem realizar com vari veis constantes e valores desses
50. mplo int const m ximo de alunos por turma 50 int alunos na turma 10 e Os nomes de fun es ou procedimentos devem ser escritos em min sculas usando se letras mai sculas iniciais em todas as palavras excepto a primeira int n meroDeAlunos Recomenda es mais gerais sobre nomes e formato de nomes em C podem ser encontradas no Ap ndice D 3 2 17 Declara o vs defini o Antes de se poder invocar uma rotina necess rio que esta seja declarada i e que o compila dor saiba que ela existe e qual a sua interface Declarar uma rotina consiste pois em dizer qual o seu nome qual o tipo do valor devolvido quantos par metros tem e de que tipo s o esses par metros Ou seja declarar consiste em especificar o cabe alho da rotina Por exemplo void imprimeValorL gico bool b ou simplesmente visto que o nome dos par metros irrelevante numa declara o void imprimeValorL gico bool s o poss veis declara es da fun o imprimeValorL gico que se define abaixo Imprime verdadeiro ou falso consoante o valor l gico do argumento pre PC V post CO surge escrito no ecr verdadeiro ou falso conforme o valor de b void imprimeValorL gico bool b if b cout lt lt verdadeiro else cout lt lt falso 96 CAP TULO 3 MODULARIZA O ROTINAS Como se viu na declara o n o necess rio indicar os nomes dos par metros
51. nda chamada em tr s locais diferentes Em cada um deles escreveu se o nome da fun o seguida de uma lista de duas express es A estas express es chama se argumentos passados fun o 72 CAP TULO 3 MODULARIZA O ROTINAS Quando calculadas essas express es t m os valores que se pretende que sejam usados para inicializar as vari veis m e n definidas na fun o madc Para o conseguir as vari veis m e n n o devem ser vari veis normais definidas dentro da caixa devem ser par metros da fun o Os par metros da fun o s o definidos entre par nteses logo ap s o nome da fun o e n o dentro da caixa ou corpo da fun o e servem como entradas da fun o fazendo parte da sua interface mdc int m int n int ky if m lt n k m else k n while m k 0 or n k 0 es A fun o mdc que um m dulo j tem entradas que correspondem aos dois par metros definidos Quando a fun o invocada os valores dos argumentos s o usados para inicializar os par metros respectivos Claro que isso implica que o n mero de argumentos numa invoca o de uma fun o tem de ser rigorosamente igual ao n mero de par metros da fun o salvo em alguns casos que se ver o mais tarde E os tipos dos argumentos tamb m t m de ser compat veis com os tipos dos par metros muito importante distinguir entre a defini o de uma rotina neste caso um fun o e a sua invoca o ou chamada A de
52. nst b if a lt hb return a else return b 102 CAP TULO 3 MODULARIZA O ROTINAS Repare se que se aproveitou para melhorar a modulariza o do programa acrescentando uma fun o para calcular o m nimo de dois valores 3 2 19 Instru es de asser o Que deve suceder quando o contrato de uma rotina violado A viola o de um contrato decorre sempre sem excep o de um erro de programa o E muito importante perceber se que assim Em primeiro lugar tem de se distinguir claramente os pap is dos v rios intervenientes no processo de escrita e execu o de um programa programador produtor aquele que escreveu uma ferramenta tipicamente um m dulo e g uma rotina programador consumidor aquele que usa uma ferramenta tipicamente um m dulo e g uma rotina com determinado objectivo utilizador do programa aquele que faz uso do programa A responsabilidade pela viola o de um contrato nunca do utilizador do programa A res ponsabilidade sempre de um programador Se a pr condi o de uma rotina for violada a responsabilidade do programador consumidor da rotina Se a condi o objectivo de uma rotina for violada e admitindo que a respectiva pr condi o n o o foi a responsabilidade do programador fabricante dessa rotina Se uma pr condi o de uma rotina for violada o contrato assinado entre produtor e consu midor n o v lido e portanto o produtor livr
53. orma muito simples basta passar a op o DNDEBUG ao compilador 3 2 20 Melhorando m dulos j produzidos Uma das vantagens da modulariza o como se viu que se pode melhorar a implementa o de qualquer m dulo sem com isso comprometer o funcionamento do sistema e sem obrigar a qualquer outra altera o Na vers o do programa da soma de frac es que se segue utiliza se uma fun o de c lculo do mdc com um algoritmo diferente mais eficiente o algoritmo de Euclides que decorre naturalmente das seguintes propriedades do mdc lembra se das suges t es no final do Cap tulo 1 1 mde m n mde n m m se0O lt mAa0 lt n 2 mde m n nsem DADA O algoritmo usado deixa de ser uma busca exaustiva do mdc para passar a ser uma redu o sucessiva do problema at trivialidade a aplica o sucessiva da propriedade vai reduzindo os valores at um deles ser zero A demonstra o da sua correc o faz se exactamente da 3 2 FUN ES E PROCEDIMENTOS ROTINAS 113 mesma forma que no caso da busca exaustiva e fica como exerc cio para o leitor Regresse se a este algoritmo depois de ter lido sobre metodologias de desenvolvimentos de ciclos no Cap tulo 4 Aproveitou se ainda para relaxar as pr condi es da fun o uma vez que o algoritmo utili zado permite calcular o mdc de dois inteiros m e n qualquer que seja m desde que n seja positivo Este relaxar das pr condi es permite que o programa
54. orno com devolu o do valor 1 Assim as vari veis e constantes locais s o retiradas da pilha o endere o de retorno 3B retirado da pilha o valor de devolu o 1 colocado ap s o topo da pilha e a execu o continua na instru o 3B ficando a pilha indicada em e na Figura 3 3 A instru o 3B consiste numa instru o de retorno com devolu o do valor n 1 ou seja 2 em que n tem o valor 2 e o 1 o valor de devolu o da chamada anterior que ficou ap s o topo da pilha Assim as vari veis e constantes locais s o retiradas da pilha o endere o de retorno 3B retirado da pilha o valor de devolu o 2 colocado ap s o topo da pilha e a execu o continua na instru o 3B ficando a pilha indicada em f na Figura 3 3 A instru o 3B consiste numa instru o de retorno com devolu o do valor n 2 ou seja 6 em que n tem o valor 3 e o 2 o valor de devolu o da chamada anterior que ficou ap s o topo da pilha Assim as vari veis locais e constantes locais s o retiradas da pilha o endere o de retorno 4B retirado da pilha o valor de devolu o 6 colocado ap s o topo da pilha e a execu o continua na instru o 4B ficando a pilha indicada em g na Figura 3 3 A instru o 4B corresponde simplesmente a escrever no ecr o valor devolvido pela chamada fun o ou seja 6 que 3 o factorial de 3 de notar que terminadas todas as chamadas fun o a pilha
55. os sendo vari veis locais autom ticas s o sempre inicializados com o valor dos argumentos respectivos Sempre que poss vel deve se inicializar explicitamente as vari veis com valores apropriados Mas nunca se deve inicializar com qualquer coisa s para o compilador n o chatear 3 2 16 Nomes de rotinas Tal como no caso das vari veis o nome das fun es e dos procedimentos dever reflectir cla ramente aquilo que calculado ou aquilo que feito respectivamente Assim as fun es t m tipicamente o nome da entidade calculada e g seno co seno comprimento enquanto os procedimentos t m normalmente como nome a terceira pessoa do singular do im perativo do verbo indicador da ac o que realizam possivelmente seguido de complementos e g acrescenta copiaSemDuplica es S se devem usar abreviaturas quando forem bem conhecidas tal como o caso em mdc Uma excep o a estas regras d se para fun es cujo resultado um valor l gico ou booleano Nesse caso o nome da fun o deve ser um predicado sendo o sujeito um dos argumentos da fun o de modo que a frase completa seja uma proposi o verdadeira ou falsa Por exemplo est Vazia fila Os nomes utilizados para vari veis fun es e procedimentos e em geral para qualquer outro identificador criado pelo programador devem ser tais que a leitura do c digo se fa a da forma mais simples poss vel quase como se de po
56. ossa ser utilizada no programa desenvolvido necess rio que a sua defini o se encontre antes da primeira utiliza o include lt iostream gt using namespace std Calcula e devolve o m ximo divisor comum de dois inteiros positivos passados como argumentos Opre PC 0 lt ma0 lt n post CO mdc mdc m n Assume se que m e n n o mudam de valor int mdc int m int n int k if m lt n k m else k n while m k 0 orn k 0 Calcula e escreve a soma em termos m nimos de duas frac es positivas lidas do teclado int main Leitura das frac es do teclado cout lt lt Introduza duas frac es ine ni db n2 d2 cin gt gt ni S gt gt gt n2 gt S d2 int k mdc nl dl nl k dl k 3 2 FUN ES E PROCEDIMENTOS ROTINAS 77 k mdc n2 d2 n2 k d2 k C lculo da frac o soma em termos m nimos int n nl d2 n2 di int d d1 d2 k mdc n d n k d k Escrita do resultado cout lt lt A soma de escreveFrac o n1 d1 cout lt lt com escreveFrac o n2 d2 cout lt lt T T escreveFrac o n d cout lt lt lt lt endl 3 2 6 Sintaxe e sem ntica da invoca o ou chamada Depois de definidas as rotinas podem ser utilizadas noutros locais de um programa A uti liza o t pica corresponde a invocar ou chamar a rotina para que seja execu
57. otina tentar alterar o valor de um par metro constante o compilador assinalar o erro O mesmo argumento pode 100 CAP TULO 3 MODULARIZA O ROTINAS ser aplicado n o s a par metros mas a qualquer vari vel se n o suposto que o seu valor mude depois de inicializada ent o deveria ser uma constante e n o uma vari vel No entanto do ponto de vista do consumidor de uma rotina a const ncia de um par metro correspondente a uma passagem de argumentos por valor perfeitamente irrelevante para o consumidor da rotina suficiente saber que ela n o alterar o argumento A altera o ou n o do par metro um pormenor de implementa o e por isso importante apenas para o produtor da rotina Assim comum indicar se a const ncia de par metros associados a passagens de argumentos por valor apenas na defini o das rotinas e n o na sua declara o Estas ideias aplicadas ao programa da soma de frac es conduzem a include lt iostream gt using namespace std Reduz a frac o passada com argumento na forma de dois inteiros positivos Opre PC n n d dA A0 lt n 0 lt d post CO 3 S Amdc n d 1 void reduzFrac o int amp n int amp d Escreve no ecr uma frac o no formato usual que lhe passada na forma de dois argumentos inteiros positivos pre PC V ou seja nenhuma pr condi o post CO o ecr cont m n d emque n e d s oosvaloresde n e d representados em base
58. pre PC 0 lt mad lt n post CO mdc mde m n int mdc int const m int const n 112 CAP TULO 3 MODULARIZA O ROTINAS assert 0 lt n and 0 lt d int k m nimo m n while m k 0 or n k 0 k assert m k 0 and n k 0 return k Estas dificuldades n o devem levar ao abandono pura e simples do esfor o de expressar pr condi es e condi es objectivo na forma de instru es de asser o A vantagem das instru es de asser o por si s enorme al m de que o esfor o de as escrever exige uma completa com preens o do problema o que leva naturalmente a menos erros na implementa o da respectiva resolu o A coloca o criteriosa de instru es de asser o pois um mecanismo extremamente til para a depura o de programas Mas tem uma desvantagem aparente as verifica es da asser es consomem tempo Para qu ent o continuar a fazer essas verifica es quando o programa j estiver liberto de erros O mecanismo das instru es de asser o interessante porque permite evitar esta desvantagem com eleg ncia basta definir uma macro de nome NDEBUG no debug para que as asser es deixem de ser verificadas e portanto deixem de consumir tempo n o sendo necess rio apag las do c digo As macros ser o explicadas no Cap tulo 9 sendo suficiente para j saber que a maior parte dos compiladores para Unix ou Linux permitem a defini o dessa macro de uma f
59. ra o ou perman ncia de vari veis Quando que as vari veis existem i e t m espa o de mem ria reservado para elas As vari veis globais existem sempre desde o in cio ao fim do programa e por isso dizem se est ticas S o constru das no in cio do programa e destru das no seu final As vari veis locais incluindo par metros de rotinas existem em mem ria apenas enquanto o bloco de instru es em que est o inseridas est a ser executado sendo assim potencialmente constru das e destru das muitas vezes ao longo de um programa Vari veis com estas caracte r sticas dizem se autom ticas 94 CAP TULO 3 MODULARIZA O ROTINAS As vari veis locais tamb m podem ser est ticas desde que se preceda a sua defini o do qua lificador static Nesse caso s o constru das no momento em que a execu o passa pela primeira vez pela sua defini o e s o destru das deixam de existir no final do programa Este tipo de vari veis usa se comummente como forma de definir vari veis locais que preservam o seu valor entre invoca es da rotina em que est o definidas Inicializa o As vari veis de tipos b sicos podem n o ser inicializadas explicitamente Quando isso acon tece as vari veis est ticas s o inicializadas implicitamente com um valor nulo enquanto as vari veis autom ticas por uma quest o de efici ncia n o s o inicializadas de todo passando portanto a conter lixo Recorde se que os par metr
60. rador b sico corresponde na realidade a v rios operadores com o mesmo nome i e sobrecarregados cada um para determinado tipo dos operandos A assinatura de uma rotina corresponde sequ ncia composta pelo seu nome pelo n mero de par metros e pelos tipos dos par metros Por exemplo as fun es soma acima t m as seguintes assinaturas e soma int int e soma int int int e soma float float e soma double double O tipo de devolu o de uma rotina n o faz parte da sua assinatura n o servindo portanto para distinguir entre fun es ou procedimentos sobrecarregados Num cap tulo posterior se ver que poss vel sobrecarregar os significados dos operadores b sicos como o operador quando aplicados a tipos definidos pelo programador o que transforma o C numa linguagem que se artilha de uma forma muito elegante e potente 3 6 Par metros com argumentos por omiss o O C permite a defini o de rotinas em que alguns par metros t m argumentos por omiss o Le se n o forem colocados os argumentos respectivos numa invoca o da rotina os par me tros ser o inicializados com os valores dos argumentos por omiss o Mas com uma restri o os par metros com argumentos por omiss o t m de ser os ltimos da rotina Por exemplo a defini o int soma int const a int const b pol So O vs int const c int const d return a b c d 12A const ncia de um par metro desde q
61. ras mas o mecanismo est escondido numa caixa Num autom vel toda a mec nica est escondida sob o capot Para o consumidor o interior a implementa o de um m dulo irrelevante o audi filo s se importa com a constitui o interna de um m dulo na medida em que ela determina o seu comportamento externo O consumidor de um m dulo s precisa de conhecer a sua fun o e a sua interface A sua vis o de um m dulo permite lhe abstraindo se do seu funcionamento interno preocupar se apenas com aquilo que lhe interessa ouvir som de alta fidelidade A modulariza o o encapsulamento e a abstrac o s o conceitos fundamentais em engenharia da programa o para o desenvolvimento de programas de grande escala Mesmo para peque nos programas estes conceitos s o teis quando mais n o seja pelo treino que proporciona a 3 1 INTRODU O MODULARIZA O 61 sua utiliza o e que permite ao programador mais tarde lidar melhor com projectos de maior escala Estes conceitos ser o estudados com mais profundidade em disciplinas posteriores como Concep o e Desenvolvimento de Sistemas de Informa o e Engenharia da Programa o Neste cap tulo far se uma primeira abordagem aos conceitos de modulariza o e de abstrac o em programa o Os mesmos conceitos ser o revisitados ao longo dos cap tulos subsequentes As vantagens da modulariza o para a programa o s o pelo menos as seguintes 2 1 facilita a de
62. riviais pode se es crever a sua solu o na forma do passo de um algoritmo ou instru o de um programa Cada problema ou sub problema identificado corresponde normalmente a uma rotina no programa final Esta abordagem n o est isenta de problemas Um deles o de n o facilitar o reaproveitamento de c digo que dois sub problemas podem ser iguais sem que o programador d por isso o que resulta em duas rotinas iguais ou pelo menos muito parecidas Assim muitas vezes conveniente alternar a abordagem descendente com a abordagem ascendente Na abordagem ascendente come a por se tentar perceber que ferramentas fazem falta para resolver o problema mas n o est o ainda dispon veis Depois desenvolvem se essas ferramen tas que correspondem tipicamente a rotinas e repete se o processo indo sempre acrescen tando camadas de ferramentas sucessivamente mais sofisticadas linguagem A desvantagem deste m todo que dificilmente se pode saber que ferramentas fazem falta sem um m nimo de abordagem descendente Da a vantagem de alternar as abordagens Suponha se que se pretende escrever um programa que some duas frac es positivas intro duzidas do teclado e mostre o resultado na forma de uma frac o reduzida ou em termos m nimos Recorda se que uma frac o 4 est em termos m nimos se n o existir qualquer di visor comum ao numerador e ao denominador com excep o de 1 ou seja se mdc m n 1 Para simplificar admite
63. rtugu s se tratasse Idealmente os procedimentos t m um nico objectivo sendo por isso descrit veis usando ape nas um verbo Quando a descri o rigorosa de um procedimento obrigar utiliza o de dois ou mais verbos isso indicia que o procedimento tem mais do que um objectivo sendo por isso um fort ssimo candidato a ser dividido em dois ou mais procedimentos A linguagem C imperativa i e os programas consistem em sequ ncias de instru es Assim o corpo de uma fun o diz como se calcula qualquer coisa mas n o diz o que se calcula de toda a conveni ncia que usando as regras indicadas esse o que fique o mais poss vel expl cito no nome da fun o passando se o mesmo quanto aos procedimentos Isto claro est No caso de m todos de classes ver Cap tulo 7 o sujeito o objecto em causa ou seja o objecto para o qual o m todo foi invocado 3 2 FUN ES E PROCEDIMENTOS ROTINAS 95 n o excluindo a necessidade de comentar fun es e procedimentos com as respectivas PC e CO Finalmente de toda a conveni ncia que se use um estilo de programa o uniforme Tal faci lita a compreens o do c digo escrito por outros programadores ou pelo pr prio programador depois de passados uns meses sobre a escrita do c digo Assim sugerem se as seguintes regras adicionais e Os nomes de vari veis e constantes devem ser escritos em min sculas usando se o subli nhado _ para separar as palavras Por exe
64. s As vari veis locais podem ser definidas em qualquer ponto de uma rotina onde possa estar uma instru o s vari veis que se definem fora de qualquer rotina chama se vari veis globais Os mesmos nomes se aplicam no caso das constantes h constantes locais e constantes globais Os par metros de uma rotina s o vari veis locais como quaisquer outras excepto quanto sua forma de inicializa o os par metros s o inicializados implicitamente com o valor dos argumentos respectivos em cada invoca o da rotina 3 2 13 Blocos de instru es ou instru es compostas Por vezes conveniente agrupar um conjunto de instru es e trat las como uma nica instru o Para isso envolvem se as instru es entre Por exemplo no c digo double raiol raio2 if raiol lt raio2 double const aux raiol raiol raio2 raio2 aux as tr s instru es 90 CAP TULO 3 MODULARIZA O ROTINAS double const aux raiol raiol raio2 raio aux est o agrupadas num nico bloco de instru es ou numa nica instru o composta com execu o dependente da veracidade de uma condi o Um outro exemplo simples de um bloco de instru es o corpo de uma rotina Os blocos de instru es podem estar embutidos ou aninhados dentro de outros blocos de instru es Por exemplo no programa int main INE iy cin gt gt n if n lt 0 cout lt lt Valor negativo Usando o m dulo n n
65. s da primeira utiliza o 92 CAP TULO 3 MODULARIZA O ROTINAS Em cada contexto s pode ser definida uma vari vel com o mesmo nome Por exemplo int J int k into jg erro j definida pela segunda vez float k erro k definida pela segunda vez Por outro lado o mesmo nome pode ser reutilizado em contextos diferentes Por exemplo no programa da soma de frac es utiliza se o nome n em contextos diferentes int mdc int m int n int main int n nl ada2 n dI Em cada contexto n uma vari vel diferente Quando um contexto se encontra embutido ou aninhado dentro de outro as vari veis vis veis no contexto exterior s o vis veis no contexto mais interior excepto se o contexto interior definir uma vari vel com o mesmo nome Neste ltimo caso diz se que a defini o interior oculta a defini o mais exterior Por exemplo no programa double f 1 0 int main f 2 0 else double f 3 0 cout lt lt f lt lt endl cout lt lt f lt lt endl 3 2 FUN ES E PROCEDIMENTOS ROTINAS 93 a vari vel global vis vel desde a sua defini o at ao final do programa incluindo o bloco de instru es ap s o if que est embutido no corpo de main mas excluindo o bloco de instru es ap s o else tamb m embutido em main no qual uma outra vari vel como mesmo nome definida e portanto vis vel Mesmo quando existe oculta o de uma vari
66. s vari veis t m posi es de mem ria associadas a chamada troca 20 a b n o faz qualquer sentido e conduz a dois erros de compila o E de notar que a utiliza o de passagens por refer ncia deve ser evitada a todo o custo em fun es pois levariam ocorr ncia de efeitos laterais nas express es onde essas fun es fossem chamadas Isto evita situa es como int incrementa int amp valor return valor valor 1 int main int i O cout lt lt i incrementa i lt lt endl em que o resultado final tanto pode ser aparecer 1 como aparecer 2 no ecr dependendo da or dem de c lculo dos operandos da adi o Ou seja fun es com par metros que s o refer ncias s o meio caminho andado para instru es mal comportadas que se discutiram na Sec o 2 7 8 Assim as passagens por refer ncia s se devem usar em procedimentos e mesmo a com par cim nia Mais tarde ver se que existe o conceito de passagem por refer ncia constante que permite aliviar um pouco esta recomenda o ver Sec o 5 2 11 Uma observa o atenta do programa para c lculo das frac es desenvolvido mostra que este cont m instru es repetidas que mereciam ser encapsuladas num procedimento s o as ins tru es de redu o das frac es aos termos m nimos identificadas abaixo em negrito 86 CAP TULO 3 MODULARIZA O ROTINAS include lt iostream gt using
67. scrita do resultado cout lt lt A soma de escreveFfrac o nl d1 cout lt lt com T escreveFrac o n2 d2 cout lt lt T m escreveFrac o n d cout lt lt lt lt endl void reduzFrac o int amp n int amp d assert d 0 if d lt 0 n n q d int const k mdc n d n k d k assert 0 lt d and mdc n d 1 void escreveFrac o int const n int const d cout lt lt n lt lt lt lt d int mdc int m int n assert 0 lt n if m lt 0 m m while m 0 int const auxiliar n m n m m auxiliar return n 3 3 ROTINAS RECURSIVAS 115 3 3 Rotinas recursivas O C como a maior parte das linguagens de programa o imperativas permite a defini o daquilo a que se chama rotinas recursivas Diz se que uma rotina recursiva se o seu corpo incluir chamadas pr pria rotina Por exemplo Devolve o factorial do inteiro passado como argumento Opre PC 0 lt n post CO factorial n ou ainda factorial TIL 5 int factorial int const n if n 0 or n 1 return 1 return n factorial n 1 uma fun o recursiva que calcula o factorial e que foi obtida de uma forma imediata a partir da defini o recorrente do factorial ita n n 1 se0 lt n 1 sen 0 2 usando se adicionalmente o facto de que 1 tamb m 1 Este tipo de rotinas pode ser mu
68. se que as frac es introduzidas s o representadas cada uma por um par de valores inteiros positivos numerador e denominador Pode se come ar por escrever o esqueleto do programa finclude lt iostream gt 64 CAP TULO 3 MODULARIZA O ROTINAS using namespace std Calcula e escreve a soma em termos m nimos de duas frac es positivas lidas do teclado int main Olhando o problema na globalidade verifica se que pode ser dividido em tr s sub problemas ler as frac es de entrada obter a frac o soma em termos m nimos e escrever o resultado Traduzindo para C include lt iostream gt using namespace std Calcula e escreve a soma em termos m nimos de duas frac es positivas lidas do teclado int main Leitura das frac es do teclado C lculo da frac o soma em termos m nimos Escrita do resultado Pode se agora abordar cada sub problema independentemente Come ando pela leitura das frac es identificam se dois sub sub problemas pedir ao utilizador para introduzir as frac es e ler as frac es Estes problemas s o t o simples de resolver que se passa directamente ao c digo include lt iostream gt using namespace std Calcula e escreve a soma em termos m nimos de duas frac es positivas lidas do teclado int main Leitura das frac es do teclado 3 2 FUN ES E PROCEDIMENTOS ROTINAS 65
69. tada com um de terminado conjunto de entradas A invoca o da fun o mac definida acima pode ser feita como se segue int x 5 1 int divisor 2 divisor mdc x 3 6 3 cout lt lt divisor lt lt endl 4 A sintaxe da invoca o de rotinas consiste simplesmente em colocar o seu nome seguido de uma lista de express es separadas por v rgulas em n mero igual aos dos seus par metros A estas express es chama se argumentos Os valores recebidos pelos par metros de uma rotina e o valor devolvido por uma fun o po dem ser de qualquer tipo b sico do C ou come ar se a falar destes tipos no Cap tulo de tipos de dados definidos pelo programador 5 O tipo de um argumento tem de ser compa t vel com o tipo do par metro respectivo Como evidente uma fun o pode devolver um nico valor do tipo indicado no seu cabe alho Uma invoca o de uma fun o pode ser usada em express es mais complexas tal como qual quer operador dispon vel na linguagem uma vez que as fun es devolvem um valor calcu N o esquecer que todas as express es em C s o de um determinado tipo 78 CAP TULO 3 MODULARIZA O ROTINAS lado No exemplo acima a chamada fun o mdc usada como segundo operando de uma opera o de atribui o instru o 3 Que acontece quando o c digo apresentado executado Instru o 1 constru da uma vari vel x inteira com valor inicial
70. tec o de erros pois em princ pio simples identificar o m dulo respons vel pelo erro reduzindo se assim o tempo gasto na identifica o de erros 2 permite testar os m dulos individualmente em vez de se testar apenas o programa com pleto o que reduz a complexidade do teste e permite come ar a testar antes de se ter completado o programa 3 permite fazer a manuten o do programa correc o de erros melhoramentos etc m dulo a m dulo e n o no programa globalmente o que reduz a probabilidade de essa manuten o ter consequ ncias imprevistas noutras partes do programa 4 permite o desenvolvimento independente dos m dulos o que simplifica o trabalho em equipa pois cada elemento ou cada sub equipa tem a seu cargo apenas alguns m dulos do programa e 5 permite a reutiliza o do c digo desenvolvido que porventura a mais evidente van tagem da modulariza o em programas de pequena escala Um programador assume ao longo do desenvolvimento de um programa dois papeis distin tos por um lado produtor pois sua responsabilidade desenvolver m dulos por outro consumidor pois far com certeza uso de outros m dulos desenvolvidos por outrem ou por ele pr prio no passado Esta uma no o muito importante de toda a conveni ncia que um programador possa ser um mero consumidor dos m dulos j desenvolvidos sem se preocupar com o seu funcionamento interno basta lhe como consumidor sabe qu
71. tiliza uma parte da mem ria do computador como se de uma pilha se tratasse i e como um local onde se pode ir acumulando informa o de tal forma que a ltima informa o a ser colocada na pilha seja a primeira a ser retirada um pouco como acontece com as pilhas de processos das reparti es p blicas em os processos dos incautos podem ir envelhecendo ao longo de anos na base de uma pilha A pilha utilizada para colocar todas as vari veis locais autom ticas quando estas s o cons tru das O topo da pilha varia quando executada uma instru o de defini o de um vari vel autom tica As vari veis definidas s o colocadas constru das no topo da pilha e apenas s o retiradas destru das quando se abandona o bloco onde foram definidas tamb m na pilha que se guarda o endere o da instru o para onde o fluxo de execu o do programa deve retor nar uma vez terminada a execu o de uma rotina No fundo a pilha serve para o computador saber a quantas anda Exemplo n o recursivo Suponha se o seguinte programa incluindo a fun o mdc include lt iostream gt using namespace std Calcula e devolve o m ximo divisor comum de dois inteiros passados como argumentos o segundo inteiro tem de ser positivo Opre PC m mAn nA0 lt n post CO mdc mde ml n int mdc int const m int const n assert 0 lt n if m lt 0 mo 118 CAP TULO 3 MODULARIZA O ROT
72. tipos Uma maneira de ver as rotinas como extens es a essas opera es dispon veis na lingua gem n o artilhada Por exemplo o C n o fornece qualquer opera o para calcular o mdc m ximo divisor comum mas no Cap tulo 1 viu se uma forma de o calcular O peda o de pro grama que calcula o mdc pode ser colocado numa caixa preta com uma interface apropriada de modo a que possa ser reutilizado sempre que necess rio Isso corresponde a definir uma fun o chamada madc que pode mais tarde ser utilizada onde for necess rio calcular o m ximo divisor comum de dois inteiros cout lt lt Introduza dois inteiros int m n cin gt gt m gt gt i cout lt lt mdc lt lt m lt lt lt lt n lt lt lt lt mde m n lt lt endl Assim ao se produzirem rotinas est se como que a construir uma vers o mais potente da lin guagem de programa o utilizada interessante que muitas tarefas em programa o podem ser interpretadas exactamente desta forma Em particular ver se mais tarde que poss vel aplicar a mesma ideia aos tipos de dados dispon veis o programador pode n o apenas arti lhar a linguagem com novas opera es sobre tipos b sicos como tamb m com novos tipos 2A linguagem C n o distingue entre fun es e procedimentos ambos s o conhecidos simplesmente por fun es nas refer ncias t cnicas sobre a linguagem 3 2 FUN ES E PROCEDIMENTOS ROTI
73. tivo em asser es em geral uma tarefa mais dif cil que no caso das pr condi es que tendem a ser mais simples As maiores dificuldades surgem es pecialmente se a condi o objectivo contiver quantificadores somat rios produtos quaisquer que seja existe uns etc se estiverem envolvidas inser es ou extrac es de canais entradas e sa das ou se a condi o objectivo fizer men o aos valores originais das vari veis i e ao valor que as vari veis possuiam no in cio da rotina em causa Considere se cada uma das rotinas do programa O caso da fun o m nimo f cil de resolver pois a condi o objectivo traduz se facilmente para C E necess rio no entanto abandonar os retornos imediatos e guardar o valor a 110 CAP TULO 3 MODULARIZA O ROTINAS devolver numa vari vel a usar na asser o Devolve o menor de dois inteiros passados como argumentos Opre PC V ou seja nenhuma pr condi o post CO m nimo a a lt b V m nimo b b lt a int m nimo int const a int const b int m nimo if a lt b m nimo a else m nimo b assert m nimo a and a lt b or m nimo b and b lt a return m nimo Quanto ao procedimento reduzFrac o f cil verificar o segundo termo da condi o objectivo Reduz a frac o passada com argumento na forma de dois inteiros positivos Opre PC n nAd dA0O lt nAd lt d post CO amp Amde n d 1
74. to s o vis veis apenas as vari veis me n de mdc A execu o passa ent o para o corpo da fun o onde durante o ciclo a constante local auxiliar constru da e destru da no topo da pilha v rias vezeg at que o ciclo termina com valor de sejado na vari vel n i e 2 Assim imediatamente antes da execu o da instru o de retorno a pilha cont m Qualquer compilador minimamente inteligente evita este processo de constru o e destrui o repetitivas cons truindo a vari vel auxiliar na pilha logo no in cio da invoca o da fun o 120 CAP TULO 3 MODULARIZA O ROTINAS maint m int retorno a 2B m int 5 A instru o de retorno come a por calcular o valor a devolver neste caso o valor de n i e 2 retira da pilha destr i todas as vari veis desde o topo at ao pr ximo endere o de retorno retorno a 2B m int 5 e em seguida retira da pilha a instru o para onde o fluxo de execu o deve ser retomado i e 2B colocando na pilha mas para l do seu topo em situa o periclitante o valor a devolver m int ZA Em seguida a execu o continua em 2B que constr i a vari vel divisor inicializando a com o valor devolvido colocado ap s o topo da pilha que depois se deixa levar por uma corrente de ar 3 4 MECANISMO DE INVOCA O DE ROTINAS 121 d int
75. u es entre int ky if m lt n k m else k n Idealmente o corpo das rotinas deve ser pequeno contendo entre uma e dez instru es Muito raramente haver boas raz es para ultrapassar as 60 linhas A raz o para isso prende se com a dificuldade dos humanos sim os programadores s o humanos em abarcar demasiados assuntos de uma s vez quanto mais curto for o corpo de uma rotina mais f cil foi de de senvolver e mais f cil de corrigir ou melhorar Por outro lado quanto maior for uma rotina mais dif cil reutilizar o seu c digo 3 2 4 Contrato e documenta o de uma rotina A defini o de uma rotina ou melhor a sua declara o como se ver na Sec o 3 2 17 s fica realmente completa quando incluir um coment rio indicando exactamente aquilo que calcula se for uma fun o ou aquilo que faz se for um procedimento I e a defini o de uma rotina s fica completa se contiver a sua especifica o Calcula e devolve o m ximo divisor comum de dois inteiros positivos passados como argumentos Opre PC 0 lt mad lt n post CO mdc mdc m n Assume se que m e n n o mudam de valor int mdc int m int k if m lt an k m else k n int n 3 2 FUN ES E PROCEDIMENTOS ROTINAS 75 while m k 0 or n k 0 k return k Todo o texto colocado entre e ignorado pelo compilador um coment rio de bloco os coment rios come a
76. ualquer dos casos continua a haver circunst ncias nas quais as pr condi es do procedi mento podem ser violadas sempre responsabilidade do programador consumidor garantir que isso n o acontece A solu o mais simples seria usar um ciclo para pedir de novo ao uti lizador para introduzir as frac es enquanto estas n o verificassem as condi es pretendidas Tal solu o n o ser ensaiada aqui por uma quest o de simplicidade Adoptar se a solu o algo simplista de terminar o programa sem efectuar os c lculos no caso de haver problemas com os valores das frac es int main Leitura das frac es do teclado cout lt lt Introduza duas frac es ine niy ALA Ay d23 cin gt gt ni gt gt dl gt gt n2 gt gt d2 if nl lt Onor dt lt 0 or n2 lt 0 or d2 lt 0 cout lt lt Termos negativos Nada feito lt lt endl else reduzFrac o n1 d1 reduzFrac o n2 d2 C lculo da frac o soma em termos m nimos int n nl ada2 n dl int d dl d2 3 2 FUN ES E PROCEDIMENTOS ROTINAS 109 reduzFrac o n d Escrita do resultado cout lt lt A soma de escreveFfrac o nl d1 cout lt lt T eom T3 escreveFrac o n2 d2 cout lt lt m M escreveFrac o n d cout lt lt lt lt endl Neste caso evidente que n o haver viola o de nenhuma pr condi o Muitos ter o a tenta o de perguntar para que ser
77. ue n o seja um refer ncia n o afecta a assinatura pois esta reflecte a interface da rotina e n o a sua implementa o 3 6 PAR METROS COM ARGUMENTOS POR OMISS O 127 permite a invoca o da fun o soma com qualquer n mero de argumentos at 4 cout lt lt soma lt lt endl Surge 0 cout lt lt soma l lt lt endl Surge 1 cout lt lt soma l 2 lt lt endl Surge 3 cout lt lt soma l 2 3 lt lt endl Surge 6 cout lt lt soma l 2 3 4 lt lt endl Surge 10 Normalmente os argumentos por omiss o indicam se apenas na declara o de um rotina As sim se a declara o da fun o soma fosse feita separadamente da respectiva defini o o c digo deveria passar a ser int soma int const a O O int const b 0 int const c 0 int const d 0 int soma int const a int const b int const c int const d re turncac t b t d 128 CAP TULO 3 MODULARIZA O ROTINAS
78. valor int mdc int m int n int k if m lt an k m else k n while m k 0 or n k 0 Seky 98 CAP TULO 3 MODULARIZA O ROTINAS A vantagem desta disposi o que aparecem primeiro as rotinas mais globais e s mais tarde os pormenores o que facilita a leitura do c digo Poder se ia alternativamente ter declarado as rotinas fora das fun es e procedimentos em que s o necess rios Nesse caso o programa seria include lt iostream gt using namespace std Reduz a frac o passada com argumento na forma de dois inteiros positivos Opre PC n n d dA A0 lt n 0 lt d post CO 3 S Amdc n d 1 void reduzFrac o int amp n int amp d Escreve no ecr uma frac o no formato usual que lhe passada na forma de dois argumentos inteiros positivos PC V ou seja nenhuma pr condi o CO oecr cont m n d emque n e d s o os valoresde n e d representados em base decimal void escreveFrac o int n int d Calcula e devolve o m ximo divisor comum de dois inteiros positivos passados como argumentos Opre PC 0 lt ma0 lt n post CO mdc mdc m n Assume se que m e n n o mudam de valor int mdc int m int n Calcula e escreve a soma em termos m nimos de duas frac es positivas lidas do teclado int main Leitura das frac es do teclado cout lt lt Introduza duas frac es int i dl 2p d2 cin gt gt nl
79. veis de tipos inteiros guardam uma gama de valores li mitados Quando se atingir o limite inferior dessa gama o valor de k passar para o maior inteiro represent vel Da descer lentamente inteiro por inteiro at ao valor 2 que levar finalmente falsidade da guarda consequente termina o do ciclo e devolu o do valor correcto Isso ocorrer muito mesmo muito tempo depois de chamada a fun o visto que exigir exactamente 4294967288 itera es do ciclo numa m quina onde os inteiros tenham 32 bits E certamente curioso este resultado Mesmo que a pr condi o seja violada o algoritmo em algumas circunst ncias devolve o resultado correcto H duas li es a tirar deste facto 1 A fun o tal como definida demasiado restritiva Uma vez que faz sentido calcular o m ximo divisor comum de quaisquer inteiros mesmo negativos desde que n o sejam ambos nulos a fun o deveria t lo previsto desde o in cio e a pr condi o deveria ter sido consideravelmente relaxada Isso ser feito mais abaixo 2 Se o contrato violado qualquer coisa pode acontecer incluindo uma fun o devolver o resultado correcto Quando isso acontece h normalmente uma outra caracter stica desej vel que n o se verifica Neste caso a efici ncia Claro est que nem sempre a viola o de um contrato leva devolu o do valor correcto Ali s isso raramente acontece Repare se no que acontece quando se invoc
80. vel global poss vel utiliz la Para isso basta qualificar o nome da vari vel global com o operador de resolu o de mbito aplicado ao espa o nominativo global os espa os nominativos ser o estudados na Sec o 9 6 2 Por exemplo no programa double f 1 0 int main LE e f 2 0 else double f f f 10 0 cout lt lt f lt lt endl cout lt lt f lt lt endl a vari vel f definida no bloco ap s o else inicializada com o valor da vari vel global Um dos principais problemas com a utiliza o de vari veis globais tem a ver com o facto de es tabelecerem liga es entre os m dulos rotinas que n o s o expl citas na sua interface i e na informa o presente no cabe alho Dois procedimentos podem usar a mesma vari vel global ficando ligados no sentido em que a altera o do valor dessa vari vel por um procedimento tem efeito sobre o outro procedimento que a usa As vari veis globais s o assim uma fonte de erros que ademais s o dif ceis de corrigir O uso de vari veis globais por isso forte mente desaconselhado para n o dizer proibido J o mesmo n o se pode dizer de constantes globais cuja utiliza o fortemente aconselhada Outro tipo de pr tica pouco recomend vel o de ocultar nomes de contextos exteriores atra v s de defini es locais com o mesmo nome Esta pr tica d origem a erros de muito dif cil correc o 3 2 15 Du
81. vem as asser es neste momento e se n o seria apropriado elimin las H v rias raz es para as asser es continuarem a ser indispens veis 1 O programador enquanto produtor n o deve assumir nada acerca dos consumidores muito embora em muitos casos produtor e consumidor sejam uma e a mesma pessoa O melhor mesmo colocar a asser o o diabo tece as 2 O produtor deve escrever uma rotina pensando em poss veis reutiliza es futuras Pode haver erros nas futuras utiliza es pelo que o mais seguro mesmo manter a asser o 3 Se algu m fizer altera es no programa pode introduzir erros A asser o nesse caso permitir a sua r pida detec o e correc o Parece ter faltado algo em toda esta discuss o a condi o objectivo Tal como se deve usar as ser es para verificar as pr condi es tamb m se deve usar asser es para verificar as condi es objectivo A falsidade de uma condi o objectivo sabendo que a respectiva pr condi o verdadeira tamb m devida a um erro de programa o s que desta vez o respons vel pelo erro o programador produtor Assim as asser es usadas para verificar as pr condi es ser vem para o produtor de uma rotina facilitar a detec o de erros do programador consumidor enquanto as asser es usadas para verificar as condi es objectivo servem para o produtor de uma rotina se proteger dos seus pr prios erros Transformar as condi es objec
82. ver o sub problema do c lculo da frac o soma em termos m nimos Dadas duas frac es a sua soma simples se desde que tenham o mesmo denominador A forma mais simples de reduzir duas frac es diferentes ao mesmo denominador consiste em multiplicar ambos os termos da primeira frac o pelo denominador da segunda e vice versa Ou seja a c ad be ad be AA n ta ha O 3 2 FUN ES E PROCEDIMENTOS ROTINAS 67 pelo que o programa fica finclude lt iostream gt using namespace std Calcula e escreve a soma em termos m nimos de duas frac es positivas lidas do teclado int main Leitura das frac es do teclado cout lt lt Introduza duas frac es int nl dl n2s d2s cin gt gt nl gt gt dl gt gt on2 gt d C lculo da frac o soma em termos m nimos int n nl d2 n2 d1 int d d1 d2 Escrita do resultado cout lt lt A soma de escreveFfrac o nl d1 cout lt lt Tocom escreveFrac o n2 d2 cout lt lt y escreveFrac o n d cout lt lt lt lt endl Usando o mesmo exemplo que anteriormente se as frac es de entrada forem e Z o pro 9 3 grama tal como est escreve A soma de 6 9 com 7 3 81 27 Ou seja a frac o resultado n o est reduzida Para a reduzir necess rio dividir o numerador e o denominador da frac o pelo seu mdc include lt iostream gt using namespace std Cal
83. voltou sua situa o original que se sup s ser vazia indicada em h na Figura 3 3 A raz o pela qual as chamadas recursivas funcionam como espect vel que em cada cha mada aninhada s o criadas novas vers es das vari veis e constantes locais e dos par metros convenientemente inicializados da rotina Embora os exemplos acima se tenham baseado em fun es evidente que o mesmo mecanismo usado para os procedimentos embora simpli ficado pois estes n o devolvem qualquer valor 3 5 Sobrecarga de nomes Em certos casos importante ter rotinas que fazem conceptualmente a mesma opera o ou o mesmo c lculo mas que operam com tipos diferentes de dados Seria pois de todo o interesse que fosse permitida a defini o de rotinas com nomes id nticos distintos apenas no tipo dos seus par metros De facto a linguagem C apenas pro be a defini o no mesmo contexto de 3 5 SOBRECARGA DE NOMES 125 fun es ou procedimentos com a mesma assinatura i e n o apenas com o mesmo nome mas tamb m com a mesma lista dos tipos dos par metros Assim de permitida a defini o de m ltiplas rotinas com o mesmo nome desde que difiram no n mero ou tipo de par metros As rotinas com o mesmo nome dizem se sobrecarregadas A invoca o de rotinas sobrecarrega das faz se como habitualmente sendo a rotina que de facto invocada determinada a partir do n mero e tipo dos argumentos usados na invoca o Por exemplo suponh
84. x x int amp a int y int auxiliar intifrozen 1 2 1 x y x int amp gt a int int amp b int auxiliar intffrozen A 2 2 1 y auxiliar x int amp gt a int y int amp gt b int auxiliar intffrozen 2 1 1 fim de troca a int b int Figura 3 2 Diagramas com evolu o do estado do programa que invoca o procedimento troca entre cada instru o 3 2 FUN ES E PROCEDIMENTOS ROTINAS 85 1 Os par metros x e y tornam se sin nimos refer ncias das vari veis a e b Aqui n o feita a c pia dos valores de a e b para x e y O que acontece que os par metros x e y passam a referir se s mesmas posi es de mem ria onde est o guardadas as vari veis a e b Ao processo de equipara o de um par metro ao argumento respectivo passado por refer ncia chama se tamb m inicializa o No corpo do procedimento o valor que est guardado em x trocado com o valor guar dado em y Dado que x se refere mesma posi o de mem ria que a e y mesma posi o de mem ria que b uma vez que s o sin nimos ao fazer esta opera o est se efectivamente a trocar os valores das vari veis a e b Quando termina a execu o da fun o s o destru dos os sin nimos x e y das vari veis a e b que permanecem intactas ficando os valores destas trocados Como s podem existir sin nimos refer ncias de entidades que tal como a

Download Pdf Manuals

image

Related Search

Related Contents

Conceptronic Desktop 600W  Brother HL-700 Series User's Manual  LAN Alinea 19  Surf it Easy™ User Guide  HOOVEB ®  Radio Shack PRO-2056 User's Manual  Port Designs Cambridge 15.4  愛知県において火災事故(軽傷1名)が発生しました    OWNER`S MANUAL  

Copyright © All rights reserved.
Failed to retrieve file