• Nenhum resultado encontrado

A instrução de repetição for

No documento C++ Como Programar - 5ª Edição - Original (páginas 184-189)

5.5 Instrução de repetição do...while 5.6 A estrutura de seleção múltipla switch 5.7 Instruções break e continue

5.8 Operadores lógicos

5.9 Confundindo operadores de igualdade (==) com operadores de atribuição (=)

5.10 Resumo de programação estruturada

5.11 Estudo de caso de engenharia de software: identificando estados e atividades dos objetos no sistema ATM (opcional)

5.12 Síntese

Resumo | Terminologia | Exercícios de revisão | Respostas dos exercícios de revisão | Exercícios

5.1 Introdução

O Capítulo 4 iniciou nossa introdução aos tipos de bloco de construção que estão disponíveis para resolução de problemas. Utilizamos esses blocos de construção para empregar técnicas comprovadas de construção de programa. Neste capítulo, continuamos nossa apre- sentação da teoria e princípios da programação estruturada introduzindo as instruções de controle restantes do C++. As instruções de controle estudadas neste e no Capítulo 4 nos ajudarão a construir e manipular objetos. Continuamos nossa ênfase inicial em programa- ção orientada a objetos que começou com uma discussão de conceitos básicos no Capítulo 1 e extensos exemplos e exercícios de código orientado a objetos nos capítulos 3–4.

Neste capítulo, demonstramos as instruções for, do...while e as instruções switch. Por uma série de breves exemplos que utilizam

while e for, exploramos os princípios básicos da repetição controlada por contador. Dedicamos uma parte do capítulo à expansão da classe GradeBook apresentada nos capítulos 3–4. Em particular, criamos uma versão da classe GradeBook que utiliza uma instrução

switch para contar o número de notas A, B, C, D e F em um conjunto de notas baseadas em letras inseridas pelo usuário. Introduzimos as instruções de controle de programa break e continue. Discutimos os operadores lógicos, que permitem aos programadores utilizar expressões condicionais mais poderosas em instruções de controle. Examinamos também o erro comum de confundir os operadores de igualdade (==) com os operadores de atribuição (=) e como evitá-lo. Por fim, resumimos as instruções de controle e as comprovadas técnicas de resolução de problemas do C++ apresentadas neste capítulo e no Capítulo 4.

5.2 Princípios básicos de repetição controlada por contador

Esta seção utiliza a instrução de repetição while introduzida no Capítulo 4 para formalizar os elementos necessários à realização da repetição controlada por contador. Repetição controlada por contador requer

1. o nome de uma variável de controle (ou contador de loop); 2. o valor inicial da variável de controle;

3. a condição de continuação do loop que testa o valor final da variável de controle (isto é, se o loop deve continuar) e 4. o incremento (ou decremento) pelo qual a variável de controle é modificada a cada passagem pelo loop.

Considere o programa simples na Figura 5.1, que imprime os números de 1 a 10. A declaração na linha 9 nomeia a variável de controle (counter) e declara essa variável como um inteiro, reserva espaço para ela na memória e a configura como um valor inicial de 1. As declarações que requerem inicialização são, de fato, instruções executáveis. Em C++, é mais preciso chamar uma declaração que também reserva memória — como a declaração precedente faz — uma definição. Como as definições são também declarações, uti- lizaremos o termo ‘declaração’ exceto quando a distinção for importante.

A declaração e a inicialização de counter (linha 9) também poderiam ter sido realizadas com as instruções

int counter; // declara a variável de controle

counter = 1; // inicializa a variável de controle como 1

Utilizamos ambos os métodos de inicialização de variáveis.

A linha 14 incrementa o contador de loop por 1 toda vez que o corpo do loop é executado. A condição de continuação do loop (linha 11) na instrução while determina se o valor da variável de controle é menor que ou igual a 10 (o valor final para o qual a condição é

5.1 Introdução

Deitel_C++_Cap05.indd 141

true). Observe que o corpo deste while executa mesmo quando a variável de controle é 10. O loop termina quando a variável de controle é maior que 10 (isto é, quando counter se torna 11).

A Figura 5.1 pode se tornar mais concisa inicializando counter como 0 e substituindo a instrução while por

while ( ++counter <= 10 ) // condição de continuação do loop cout << counter << “ “;

Esse código salva uma instrução, porque a incrementação é feita diretamente na condição while antes de a condição ser testada. Além disso, o código elimina as chaves em torno do corpo de while, porque while agora contém somente uma instrução. Codificar de modo tão condensado exige certa prática e pode resultar em programas mais difíceis de ler, depurar, modificar e manter.

Erro comum de programação 5.1

Os valores de ponto flutuante são aproximados, portanto controlar a contagem de loops com variáveis de ponto flutuante pode resultar em valores de contador imprecisos e testes imprecisos para terminação.

Dica de prevenção de erro 5.1

Controle a contagem do loop com valores de inteiro.

Boa prática de programação 5.1

Coloque uma linha em branco antes e depois de cada instrução de controle para destacá-la no programa.

Boa prática de programação 5.2

Muitos níveis de aninhamento podem tornar um programa difícil de entender. De modo geral, tente evitar o uso de mais de três níveis de recuo.

Boa prática de programação 5.3

O espaçamento vertical acima e abaixo de instruções de controle e o recuo do corpo das instruções de controle dentro dos cabeçalhos de instrução de controle fornecem aos programas uma aparência bidimensional que melhora significativamente a legibilidade.

1 // Figura 5.1: fig05_01.cpp

2 // Repetição controlada por contador. 3 #include <iostream> 4 using std::cout; 5 using std::endl; 6 7 int main() 8 {

9 int counter = 1; // declara e inicializa a variável de controle 10

11 while ( counter <= 10 ) // condição de continuação do loop 12 {

13 cout << counter << “ “;

14 counter++; // incrementa a variável de controle por 1 15 } // fim do while

16

17 cout << endl; // gera a saída de um caractere de nova linha 18 return 0; // terminação bem-sucedida

19 } // fim de main

1 2 3 4 5 6 7 8 9 10

Figura 5.1 Repetição controlada por contador.

Deitel_C++_Cap05.indd 142

143

5.3 A instrução de repetição for

A Seção 5.2 apresentou os princípios básicos da repetição controlada por contador. A instrução while pode ser utilizada para implementar qualquer loop controlado por contador. O C++ também fornece a instrução de repetiçãofor, que especifica os detalhes da repetição controlada por contador em uma única linha de código. Para ilustrar a capacidade de for, vamos reescrever o programa da Figura 5.1. O resultado é mostrado na Figura 5.2.

Quando a instrução for (linhas 11–12) começa a executar, a variável de controle counter é declarada e inicializada como 1. Então, a condição de continuação do loop counter <= 10 é verificada. O valor inicial de counter é 1, então a condição é satisfeita e a instru- ção do corpo (linha 12) imprime o valor de counter, isto é, 1. Em seguida, a expressão counter++ incrementa a variável de controle

counter e o loop inicia novamente com o teste de continuação do loop. A variável de controle é agora igual a 2; portanto, o valor final não é excedido e o programa realiza a instrução de corpo novamente. Esse processo continua até o corpo do loop ter executado 10 vezes e a variável de controle counter ser incrementada para 11 — isso faz com que o teste de continuação do loop (linha 11 entre os ponto- e-vírgulas) falhe e com que a repetição termine. O programa continua executando a primeira instrução depois da instrução for (nesse caso, a instrução de saída na linha 14).

Componentes do cabeçalho da instrução for

A Figura 5.3 oferece um exame mais minucioso do cabeçalho da instrução for (linha 11) da Figura 5.2. Observe que o cabeçalho da instrução for ‘faz tudo’ — ele especifica cada um dos itens necessários para repetição controlada por contador com uma variável de controle. Se houver mais de uma instrução no corpo de for, as chaves são necessárias para incluir o corpo do loop.

Note que a Figura 5.2 utiliza a condição de continuação do loop counter <= 10. Se o programador escrevesse counter < 10

incorretamente, então o loop executaria apenas 9 vezes. Esse é um erro off-by-one.

1 // Figura 5.2: fig05_02.cpp

2 // Repetição controlada por contador com a instrução for. 3 #include <iostream> 4 using std::cout; 5 using std::endl; 6 7 int main() 8 {

9 // cabeçalho da instrução for inclui inicialização, 10 // condição de continuação do loop e incremento. 11 for ( int counter = 1; counter <= 10; counter++ ) 12 cout << counter << “ “;

13

14 cout << endl; // gera a saída de um caractere de nova linha 15 return 0; // indica terminação bem-sucedida

16 } // fim de main

1 2 3 4 5 6 7 8 9 10

Figura 5.2 Repetição controlada por contador com a instrução for.

Figura 5.3 Componentes de cabeçalho de instrução for. Valor inicial da variável de controle Condição de continuação do loop Incremento da variável de controle Palavra-chave for Nome da variável de controle Separador ponto-e-vírgula requerido Separador ponto-e-vírgula requerido Valor final da variável de controle para o qual a condição é verdadeira

for ( int counter = 1; counter <= 10; counter++ )

5.3 A instrução de repetição for

Deitel_C++_Cap05.indd 143

Erro comum de programação 5.2

Utilizar um operador relacional incorreto ou um valor final incorreto de um contador de loop na condição de uma instrução while

ou for pode causar erros off-by-one.

Boa prática de programação 5.4

Utilizar o valor final na condição de uma instrução while ou for e utilizar o operador <= relacional ajudará a evitar erros off-by- one. Para um loop utilizado para imprimir os valores de 1 a 10, por exemplo, a condição de continuação do loop deve ser counter <= 10 em vez de counter < 10 (que é um erro off-by-one) ou counter < 11 (que, porém, é correto). Muitos programadores preferem a chamada contagem baseada em zero, em que para contar 10 vezes pelo loop, counter seria inicializado como zero e o teste de continuação do loop seria counter < 10.

A forma geral da instrução for é:

for ( inicialização; condiçãoDeContinuaçãoDoLoop; incremento ) instrução

onde a expressão inicialização inicializa a variável de controle do loop, condiçãoDeContinuaçãoDoLoop determina se o loop deve con- tinuar executando (essa condição, em geral, contém o valor final da variável de controle pela qual a condição é verdadeira) e incremento incrementa a variável de controle. Na maioria dos casos, a instrução for pode ser representada por uma instrução while equivalente, como segue: inicialização; while ( condiçãoDeContinuaçãoDoLoop ) { instrução incremento; }

Há uma exceção a essa regra, que discutiremos na Seção 5.7.

Se a expressão inicialização no cabeçalho de instrução for declara a variável de controle (isto é, o tipo da variável de controle é especificado antes do nome variável), a variável de controle só pode ser utilizada no corpo da instrução for — a variável de controle não será conhecida fora da instrução for. Essa utilização restrita do nome da variável de controle é conhecida como escopo da variável. O escopo de uma variável especifica onde ele pode ser utilizado em um programa. O escopo é discutido em detalhes no Capítulo 6, “Funções e uma introdução à recursão”.

Erro comum de programação 5.3

Quando a variável de controle de uma instrução for é declarada na seção de inicialização do cabeçalho de instrução for, utilizar a variável de controle depois do corpo da instrução é um erro de compilação.

Dica de portabilidade 5.1

No padrão C++, o escopo da variável de controle declarada na seção de inicialização de uma instrução for difere do escopo em compiladores C++ mais antigos. Em compiladores pré-padrão, o escopo da variável de controle não termina no fim do bloco que define o corpo da instrução for; em vez disso, o escopo termina no fim do bloco que inclui a instrução for. O código C++ criado com compiladores C++ pré-padrão pode quebrar quando compilado em compiladores compatíveis com o padrão. Se você estiver trabalhando com compiladores pré-padrão e quiser certificar-se de que seu código funcionará com compiladores compatíveis com o padrão, há duas estratégias de programação defensivas que você pode utilizar: declarar as variáveis de controle com nomes dife- rentes em cada instrução for, ou, se preferir utilizar o mesmo nome para a variável de controle em várias instruções for, declarar a variável de controle antes da primeira instrução for.

Como veremos, as expressões inicialização e incremento podem ser listas de expressões separadas por vírgulas. As vírgulas, como utilizadas nessas expressões, são operadores vírgula, que garantem que as listas de expressões sejam avaliadas da esquerda para a direita. O operador vírgula tem a precedência mais baixa de todos os operadores C++. O valor e o tipo de uma lista de expressões separada por vírgulas são o valor e o tipo da expressão mais à direita na lista. O operador vírgula é freqüentemente utilizado em instruções for. Sua aplicação principal é permitir ao programador utilizar múltiplas expressões de inicialização e/ou múltiplas expressões de incremento. Por exemplo, pode haver diversas variáveis de controle em uma única instrução for que devem ser inicializadas e incrementadas.

Deitel_C++_Cap05.indd 144

145

Boa prática de programação 5.5

Coloque apenas expressões que envolvem as variáveis de controle nas seções de inicialização e incremento de uma instrução for. As manipulações de outras variáveis devem aparecer antes do loop (se tiverem de executar apenas uma vez, como as instruções de inicialização) ou no corpo do loop (se tiverem de executar uma vez por repetição, como as instruções de incremento ou decre- mento).

As três expressões no cabeçalho da instrução for são opcionais (mas os dois separadores ponto-e-vírgula são necessários). Se a condiçãoDeContinuaçãodoLoop for omitida, o C++ pressupõe que a condição é verdadeira, criando assim um loop infinito. Pode-se omitir a expressão inicialização se a variável de controle for inicializada anteriormente no programa. Pode-se omitir a expressão incre- mento se o incremento for calculado por instruções no corpo de for ou se o incremento não for necessário. A expressão de incremento na instrução for atua como uma instrução independente no fim do corpo de um for. Portanto, as expressões

counter = counter + 1

counter += 1

++counter counter++

são todas equivalentes na parte de incremento da instrução for (quando nenhum outro código aparece aí). Muitos programadores preferem a forma counter++, porque os loops for avaliam a expressão de incremento depois que o corpo do loop executa. A forma pós-incremento portanto parece mais natural. A variável sendo incrementada aqui não aparece em uma expressão maior, assim tanto a pré-incrementação como a pós-incrementação realmente têm o mesmo efeito.

Erro comum de programação 5.4

Utilizar vírgulas em vez dos dois ponto-e-vírgulas obrigatórios em um cabeçalho for é um erro de sintaxe.

Erro comum de programação 5.5

Colocar um ponto-e-vírgula imediatamente à direita do parêntese direito de um cabeçalho for torna o corpo dessa instrução for

uma instrução vazia. Isso normalmente é um erro de lógica.

Observação de engenharia de software 5.1

Colocar ponto-e-vírgula logo depois de um cabeçalho for é às vezes utilizado para criar um loop chamado loop de retardo. Esse loop for com um corpo vazio ainda realiza o loop pelo número indicado de vezes, não fazendo nada além de contar. Por exemplo, você poderia utilizar um loop de retardo para tornar lento um programa que está produzindo saídas na tela rápido demais para serem lidas. Mas seja cuidadoso, porque um retardo assim irá variar entre sistemas com diferentes velocidades de processador. As expressões de inicialização, condição de continuação do loop e incremento de uma instrução for podem conter expressões aritméticas. Por exemplo, se x = 2 e y = 10, e x e y não são modificados no corpo do loop, o cabeçalho for

for ( int j = x; j <= 4 * x * y; j += y / x )

é equivalente a

for ( int j = 2; j <= 80; j += 5 )

O ‘incremento’ de uma instrução for pode ser negativo, caso em que é realmente um decremento e o loop realmente conta para baixo (como mostrado na Seção 5.4).

Se a condição de continuação de loop é inicialmente falsa, o corpo da instrução for não é realizado. Em vez disso, a execução prossegue com a instrução seguinte ao for.

Freqüentemente, a variável de controle é impressa ou utilizada em cálculos no corpo de uma instrução for, mas isso não é necessário. É comum utilizar a variável de controle para controlar repetição sem nunca mencioná-la no corpo da instrução for.

Dica de prevenção de erro 5.2

Embora o valor da variável de controle possa ser alterado no corpo de uma instrução for, evite fazer isso porque essa prática pode levar a erros de lógica.

Diagrama de atividades UML da instrução for

O diagrama de atividades UML da instrução for é semelhante ao da instrução while (Figura 4.6). A Figura 5.4 mostra o diagrama de atividades da instrução for na Figura 5.2. O diagrama torna claro que a inicialização ocorre uma vez antes de o teste de continuação do loop ser avaliado pela primeira vez, e que o incremento ocorre toda vez por meio do loop depois que o corpo da instrução executa. Observe que (além de um estado inicial, setas de transição, uma agregação, um estado final e várias notas) o diagrama contém apenas

5.3 A instrução de repetição for

Deitel_C++_Cap05.indd 145

estados de ação e uma decisão. Imagine, novamente, que o programador tem um contêiner de diagramas de atividades UML de instru- ções for vazias — quantas o programador possa precisar para empilhar e aninhar com os diagramas de atividades de outras instruções de controle para formar uma implementação estruturada de um algoritmo. O programador preenche os estados de ação e símbolos de decisão com expressões de ação e condições de guarda apropriadas ao algoritmo.

No documento C++ Como Programar - 5ª Edição - Original (páginas 184-189)

Documentos relacionados