Baixe o app para aproveitar ainda mais
Prévia do material em texto
GCC 105 – LINGUAGENS DE PROGRAMAÇÃO I AULA 12 – Controle de Fluxo II 1º Semestre de 2015 Prof. Janderson Rodrigo de Oliveira Universidade Federal de Lavras Departamento de Ciência da Computação Sentenças de Iteração • Uma sentença iterativa é uma que faz com que uma sentença ou uma coleção de sentenças seja executada zero, uma ou mais vezes. • Uma construção de iteração é também chamada de um laço. • Todas as linguagens contemporâneas incluem algum método de repetir a execução de segmentos de código. A iteração é a essência do poder da computação. Sentenças de Iteração • A execução repetida de uma sentença é geralmente realizada em uma linguagem funcional por meio de recursão, em vez de construções iterativas. • Diversas categorias de sentenças de controle de iteração têm sido desenvolvidas. As principais categorias são definidas a partir de como os projetistas responderam duas questões de projeto básicas: 1. Como a iteração é controlada? 2. Onde o mecanismo de controle deve aparecer na construção de laço? Sentenças de Iteração • As possibilidades primárias para o controle de iteração são o uso de controles lógicos, de contagem ou uma combinação dos dois. • As principais escolhas para a posição do mecanismo de controle são o início ou o final do laço. – A questão não é a posição física do mecanismo de controle; em vez disso, é se o mecanismo é executado e afeta o controle antes ou após a execução do corpo da construção. Sentenças de Iteração • O corpo de uma construção de iteração é a coleção de sentenças cuja execução é controlada pela sentença de iteração. • Usa-se o termo pré-teste para dizer que o teste para completar o laço ocorre antes que o corpo do laço seja executado e pós-teste para dizer que ele ocorre após a execução. • A sentença de iteração e o corpo do laço associado formam uma construção de iteração. Laços Controlados por Contador • Uma sentença de controle iterativa de contagem tem uma variável, chamada de variável de laço, na qual o valor de contagem é mantido. • Ela também inclui alguma forma de especificar valores inicial e final da variável de laço, e a diferença entre os valores das variáveis de laço sequenciais, chamada de tamanho do passo. • As especificações de início, fim e tamanho do passo de um laço são chamadas de parâmetros do laço. Laços Controlados por Contador • Questões de projeto: 1. Qual o tipo e o escopo da variável de laço? 2. Deve ser legal para a variável ou para os parâmetros de laço serem modificados no laço? 3. Os parâmetros de laço devem ser avaliados apenas uma vez ou uma vez para cada iteração? Laços Controlados por Contador • A sentença for das linguagens baseadas em C – A forma geral da sentença for de C é: – O corpo do laço pode ser uma única sentença, uma sentença composta ou uma sentença nula. – Como as sentenças de atribuição em C produzem resultados e podem ser consideradas expressões, as expressões em uma sentença for são geralmente sentenças de atribuição. for (expressão_1; expressão_2; expressão_3) Corpo do laço Laços Controlados por Contador • A sentença for das linguagens baseadas em C – A primeira expressão é para inicialização e é avaliada uma única vez, quando a execução da sentença for inicia. – A segunda expressão é o controle do laço e é avaliada antes da execução do corpo do laço. Como é comum em C, um valor igual a zero significa falso e todos os valores diferentes de zero significam verdadeiro. – Se o valor da segunda expressão é zero, o for é terminado; caso contrário, as sentenças do corpo do laço são executadas. Laços Controlados por Contador • A sentença for das linguagens baseadas em C – A última expressão no for é executada após cada execução do corpo do laço. – Todas as expressões do for em C são opcionais. Uma segunda expressão ausente é considerada verdadeira, assim um for sem uma é potencialmente um laço infinito. – Se a primeira ou a terceira expressão estiverem ausentes, nada se presume. Por exemplo, a primeira expressão estar ausente, significa que nenhuma inicialização é realizada (note que o for em C não precisa contar). Laços Controlados por Contador • A sentença for das linguagens baseadas em C – Não existem variáveis de laço ou parâmetros de laço explícitos. Todas as variáveis envolvidas podem ser modificadas no corpo do laço. – Cada uma das expressões do for de C pode ser composta de múltiplas expressões, o que por sua vez permite múltiplas variáveis de laço que podem ser de qualquer tipo. – Quando múltiplas expressões são usadas em uma única expressão de uma sentença for, elas são separadas por vírgulas. Laços Controlados por Contador • A sentença for das linguagens baseadas em C – Exemplo: – A sentença de exemplo do for em C não precisa (e não tem) um corpo de laço. – Todas as ações desejadas são parte da sentença for propriamente dita, em vez de em seu corpo. for (contador1 = 0, contador2 = 1.0; contador1 <= 10 && contador2 <= 100.0; soma = ++contador1 + contador2, contador2 *= 2.5); Laços Controlados por Contador • A sentença for das linguagens baseadas em C – A sentença for do C99 e do C++ diferem daquela das versões antigas do C de duas maneiras: 1. Em adição a uma expressão aritmética, ela pode usar uma expressão booleana para o controle de laço. 2. A primeira expressão pode incluir definições de variáveis. Por exemplo: for (int contador = 0; contador < tamanho; contador++) { ... } Laços Controlados por Contador • A sentença for das linguagens baseadas em C – O escopo de uma variável definida na sentença for é a partir de sua definição até o final do corpo do laço. – A sentença for de Java e C# é parecida com a de C++, exceto que a expressão de controle de laço é restrita a valores booleanos. – Em todas as linguagens baseadas em C, os dois últimos parâmetros de laço são avaliados com cada iteração. Além disso, variáveis que aparecem na expressão de parâmetros de laço podem ser modificadas no corpo do laço, diferentemente de Fortran e Ada. Laços Controlados Logicamente • Em muitos casos, coleções de sentenças devem ser executadas repetidamente, mas o controle de repetição é baseado em uma expressão booleana em vez em um contador. • Para essas situações, um laço controlado logicamente é conveniente. • Na verdade, laços controlados logicamente são mais gerais do que laços controlados por contador. Laços Controlados Logicamente • Todos os laços de contagem podem ser construídos com laços lógicos, mas o inverso não é verdadeiro. • Questões de projeto: 1. O controle deve ser de pré ou pós-teste? 2. O laço controlado logicamente deve ser uma forma especial de uma laço de contagem ou uma sentença separada. Laços Controlados Logicamente • Laços controlados logicamente nas linguagens baseadas em C – As linguagens baseadas em C incluem tanto laços controlados logicamente com pré-teste quanto com pós-teste que não são formas especiais de suas sentenças iterativas controladas por contador. – Os laços lógicos com pré-teste e pós-teste têm as seguintes formas: Laços Controlados Logicamente • Laços controlados logicamente nas linguagens baseadas em C – e while (expressão_de_controle) Corpo do laço do Corpo do laço while (expressão_de_controle); Laços Controlados Logicamente • Laços controlados logicamente nas linguagens baseadas em C – Na versão com pré-teste (while), a sentença é executada enquanto a expressão for avaliada como verdadeira. – Na sentença com pós-teste (do), o corpo do laço é executado até a expressão ser avaliadacomo falsa. – A única diferença real entre o do e o while é que o do sempre faz o corpo do laço ser executado ao menos uma vez. – Em ambos os casos, a sentença pode ser composta. Laços Controlados Logicamente • Laços controlados logicamente nas linguagens baseadas em C – Laços pós-teste não são usados com frequência e podem ser perigosos, porque os programadores algumas vezes esquecem que o corpo do laço será sempre executado ao menos uma vez. – Em algumas situações, é conveniente para um programador escolher uma posição para o controle do laço em vez do início ou final deste. Laços Controlados Logicamente • Mecanismos de controle de laços posicionados pelo usuário – Como resultado dessa necessidade, algumas linguagens fornecem a capacidade de posicionar a estrutura de controle dos laços. – Tais laços têm a estrutura de laços infinitos, mas incluem saídas do laço posicionadas pelos usuários. – C, C++, Python, Ruby e C# têm saídas não rotuladas incondicionais (break). Java e Perl têm saídas incondicionais rotuladas (break em Java, last em Perl). Laços Controlados Logicamente • Mecanismos de controle de laços posicionados pelo usuário – A seguir, tem-se um exemplo de laços aninhados em Java, nos quais existe um break para fora do laço externo a partir do laço interno. loopExterno: for (linha = 0; linha < nLinhas; linhas++) for (coluna = 0; coluna < nColunas; coluna++){ soma += matriz[linha][coluna]; if (soma > 1000.0) break outerLoop; } Laços Controlados Logicamente • Mecanismos de controle de laços posicionados pelo usuário – C, C++ e Python incluem uma sentença de controle não rotulada, chamada continue, que transfere o controle para o mecanismo de menor laço que o envolve. – Essa não é uma saída, mas uma maneira de pular o resto das sentenças do laço da iteração atual sem terminar a estrutura do laço. Laços Controlados Logicamente • Mecanismos de controle de laços posicionados pelo usuário – Um valor negativo faz a sentença de atribuição ser pulada, e o controle é transferido em vez disso para o condicional no topo do laço. while (soma 1000){ lerDado(valor); if (valor < 0) continue; soma += valor; } Laços Controlados Logicamente • Mecanismos de controle de laços posicionados pelo usuário – Um valor negativo termina o laço. while (soma 1000){ lerDado(valor); if (valor < 0) break; soma += valor; } Iteração baseada em Estruturas de Dados • Apenas um tipo de estrutura de iteração adicional resta ser considerado: a iteração controlada por uma estrutura de dados. • Em vez de ter um contador ou uma expressão booleana para controlar as iterações, esses laços são controlados pelo número de elementos em uma estrutura de dados. • Perl, JavaScript, PHP, Java e C# têm este tipo de sentenças. Iteração baseada em Estruturas de Dados • Uma sentença de iteração geral baseada em dados usa uma estrutura de dados e uma função definida pelo usuário para navegar nos elementos da estrutura. • Tal função é um iterador, chamado no início de cada iteração. Cada vez que ele é chamado, retorna um elemento de uma estrutura de dados em particular em alguma ordem específica. • Uma sentença de iteração definida pelo usuário termina quando o iterador falha em encontrar mais elementos. Iteração baseada em Estruturas de Dados • A construção for das linguagens baseadas em C, por causa da sua grande flexibilidade, pode ser usada para simular uma sentença de iteração definida pelo usuário. • Exemplo: for (ptr = raiz_Arvore; ptr != null; ptr = proximoNo(ptr)){ ... } Iteração baseada em Estruturas de Dados • Em C++, iteradores para tipos definidos pelo usuário, ou classes, são implementados como funções amigas (friend) à classe ou como classes iteradoras separadas. • Em Java, os elementos de uma coleção definida pelo usuário que implementa a interface Collection pode ser visitada iterativamente com uma implementação da interface Iterator. • Em algumas linguagens, como Java e C#, uma versão melhorada da sentença for foi criada para facilitar as iterações baseadas em estruturas de dados: foreach. Desvio Incondicional • Uma sentença de desvio incondicional transfere o controle da execução para uma posição especificada no programa. • O debate mais aquecido acerca do projeto de linguagens no fim dos anos 1960 era se o uso de desvios incondicionais dever ser parte de qualquer linguagem de alto nível e, se isso ocorresse, se seu uso deveria ser restrito. • O desvio incondicional, ou goto, é a sentença mais poderosa para controlar o fluxo de execução das sentenças de um programa. Desvio Incondicional • Usar o goto sem cuidados pode levar a sérios problemas. • Sem restrições em seu uso, imposta ou pelo projeto da linguagem ou por padrões de programação, as sentenças goto podem tornar os programas muito difíceis de serem lidos e, como resultado, altamente não confiáveis e com alto custo para serem mantidos. • A legibilidade é melhor quando a ordem de execução das sentenças é quase a mesma que aquela na qual elas aparecem. Desvio Incondicional • Poucas linguagens foram projetas sem um goto – por exemplo, Java, Python e Ruby. • Entretanto, a maioria das linguagens populares o inclui. • Na prática, todas as sentenças de saída de laços vistas anteriormente são sentenças goto camufladas. Exercícios 1. Reescreva o seguinte segmento de pseudocódigo usando uma estrutura de laço de alguma linguagem baseada em C: 2. Descreva uma situação de programação específica que requer um laço de pós-teste. k = (j+13)/27 loop: if k > 10 the goto out k = k + 1 i = 3*k – 1 goto loop out: ...
Compartilhar