Aula 12 - Comandos de repetição encaixados
  • Resumo
  • Exercício 1
  • Exercício 2
  • Exercício 3
  • Exercício 4
  • Exercício 5
  • Soluções
Avalie esta aula

Comandos de repetição encaixados

Um comando de repetição pode conter outro comando de repetição, como no trecho de programa abaixo, que mostra um comando while que repete três vezes (para i variando de 1 a 3, em vermelho), e que contém um outro comando while que repete duas vezes (para j variando de 1 a 2, em verde):

i = 1; while (i<=3) {
j = 1; while (j <= 2) { printf("i=%d j=%d\n", i, j); j = j + 1; }
i = i + 1; }

O trecho acima vai executar seis vezes o comando printf, e o trecho de programa escreve na saída a seguinte sequência:

i=1, j=1
i=1, j=2
i=2, j=1
i=2, j=2
i=3, j=1
i=3, j=2

Comandos de repetição encaixados permitem uma flexibilidade muito grande no controle do processamento. Por exemplo, podemos escrever na saída um retângulo de 3 linhas por 5 colunas de caracteres asteriscos, como mostrado abaixo

*****
*****
*****
com o seguinte programa que utiliza dois comandos while encaixados:
var i, j;

i = 1;
while (i<=3) {
    // para cada linha
    // escreve a linha com um outro comando while
    j = 1;
    while (j<=5) {
        // para cada coluna escreve um asterisco
	printf("*");
        j = j + 1;
    }  
    // ao final da linha, escreve caractere final-de-linha
    printf("\n"); 
    i = i + 1;
}

Uma pequena modificação na condição de parada do comando de repetição while mais interno permite que, ao invés de um retângulo, seja escrito na saída um triângulo de asteriscos. A modificação é fazer a repetição ocorrer enquanto j<=i. Dessa forma, quando está escrevendo a primeira linha o comando printf é executado 1 vez (i é igual a 1), quando está escrevendo a segunda linha ele é executado duas vezes (i é igual a 2) e quando está escrevendo a terceira linha ele é executado três vezes (i é igual a 3).

var i, j;

i = 1;
while (i<=3) {
    // para cada linha
    // escreve a linha com um outro comando while
    j = 1;
    while (j<=i) {
        // note que repete apenas enquanto j<=i
        // para cada coluna escreve um asterisco
	printf("*");
        j = j + 1;
    }  
    // ao final da linha, escreve caractere final-de-linha
    printf("\n"); 
    i = i + 1;
}

Assim, o programa acima escreve na saída o "triângulo" de asteriscos mostrado abaixo:

*
**
***

Comandos de repetição encaixados para leitura

Podemos também fazer uso de comandos encaixados na leitura de valores da entrada. Suponha que a entrada seja composta de três linhas, em que cada linha contém cinco números inteiros, variando de 0 a 1000, como no exemplo abaixo.

100 200 300 400 500
301 123 456 321 21
345 900 643 222 1

Podemos ler os valores da entrada e encontrar o maior valor com o trecho de programa abaixo.

var i, j,
    x,    // x vai armazenar um valor lido
    max;  // max vai armazenar o maior valor lido

max = -1; // é informado que o menor valor possível de ser lido é zero
          // inicializamos max com um valor menor do que zero
i = 1;
while (i<=3) {
    // para cada linha na entrada
    // lê a linha com um outro comando while
    j = 1;
    while (j<=5) {
        // para cada coluna lê um valor e compara com o máximo
	scanf("%d", "x");
        if (x>max)
            max = x; // encontramos novo máximo
        j = j + 1;
    }  
    i = i + 1;
}
// escreve o maior valor encontrado
printf("%d\n",max); 

Note que o uso de comandos encaixados não é estritamente necessário: neste último exemplo poderíamos ter utilizado simplesmente um comando de repetição com o contador variando de 1 a 15, com o mesmo efeito. No entanto, comandos de repetição encaixados na maioria das vezes tornam a programação mais fácil, e os programas melhor organizados (nos outros exemplos acima também é possível usar apenas um comando de repetição ao invés de comandos encaixdos, mas os programas ficariam mais complexos).

 

 

Avalie este exercício

Bandeira mutante

A bandeira do reino da Nlogônia é um retângulo de 3 x 5 caracteres, ou seja, três linhas de cinco caracteres cada. Quatorze caracteres são pontos, representando os condados do reino, e um caractere é uma estrela, representando a capital, onde fica o castelo do Rei.

O problema é que o Rei constantemente altera a posição da estrela na bandeira. Ora ele quer que a estrela esteja numa posição, ora em outra. A figura abaixo mostra três exemplos de bandeiras possíveis:

Na figura, a bandeira mais à esquerda tem a estrela na linha 1, coluna 1. A bandeira do meio tem a estrela na linha 3, coluna 5. E a bandeira mais à direita a estrela está na linha 2, coluna 3.

Dada a posição da estrela na bandeira, faça um programa para escrever na saída a bandeira correspondente.

Entrada

A primeira e única linha da entrada contém dois inteiros L e C, indicando respectivamente o número da linha e o número da coluna da posição da estrela. As linhas são numeradas de 1 a L e as colunas são numeradas de 1 a C.

Saída

Seu programa deve escrever na saída a bandeira correspondente à entrada, com três linhas, cada uma contendo cinco caracteres. Utilize os caracteres . (ponto) e * (asterisco) para desenhar a bandeira.

Restrições

  • 1 ≤ L ≤ 3
  • 1 ≤ C ≤ 5

Exemplos

Entrada
1 1
Saída
*....
.....
.....

Entrada
3 2
Saída
.....
.....
.*...

Entrada
2 5
Saída
.....
....*
.....

 

 

Avalie este exercício

Bandeira da estrela solitária

O Partido Central é o maior partido político da Nlogônia. Como educação, saúde e segurança são excelentes no reino, a principal reinvindicação do Partido Central é que a bandeira oficial tenha o seu formato definido na Constituição. Segundo a proposta do Partido Central, a bandeira deverá ser um retângulo de L x C caracteres, ou seja, L linhas de C caracteres cada. Todos os caracteres, exceto um, serão pontos, e um único caractere será uma estrela. O número de linhas e o número de colunas serão sempre ímpares, e a estrela deverá ocupar a posição central da bandeira. A figura abaixo mostra três exemplos de bandeiras possíveis segundo a proposta do Partido Central.

Na figura, a bandeira mais à esquerda tem três linhas e cinco colunas. A bandeira do meio tem uma linha e três colunas. E a bandeira mais à direita tem cinco linhas e três colunas.

Dados os números de linhas e de colunas da bandeira, faça um programa para escrever na saída a bandeira correspondente, segundo a proposta do Partido Central.

Entrada

A primeira e única linha da entrada contém dois inteiros L e C, indicando respectivamente o número de linhas e o número de colunas da bandeira.

Saída

Seu programa deve escrever na saída a bandeira correspondente à entrada, com L linhas, cada linha contendo C caracteres. Utilize os caracteres . (ponto) e * (asterisco) para desenhar a bandeira.

Restrições

  • 1 ≤ L ≤ 7, L ímpar
  • 1 ≤ C ≤ 7, C ímpar

Exemplos

Entrada
3 3
Saída
...
.*.
...

Entrada
1 3
Saída
.*.

Entrada
5 3
Saída
...
...
.*.
...
...

Entrada
1 1
Saída
*

 

 

Avalie este exercício

Bandeira radical

O partido Radical da Nlogônia é pequeno mas muito ativo. Apesar do nome, o partido não quer alterar o sistema de governo, mas apenas garantir uma maior descentralização administrativa.

O partido também propõe uma mudança na bandeira nacional, para refletir suas ideias avançadas. A bandeira deverá ter L x C caracteres, ou seja, L linhas de C caracteres cada. Os caracteres usados na bandeira são pontos e estrelas. Todos os caracteres de uma mesma linha são do mesmo tipo: todos os caracteres da primeira linha são pontos, todos os caracteres da segunda linha são estrelas, os caracteres da terceira linha são pontos, os da quarta linha são estrelas e assim por diante. A figura abaixo mostra dois exemplos de bandeiras possíveis:

Na figura, a bandeira à esquerda tem três linhas e cinco colunas, e a bandeira à direita tem seis linhas e três colunas.

Dados os números de linhas e de colunas da bandeira, faça um programa para escrever na saída a bandeira correspondente à proposta do Partido Radical.

Entrada

A primeira e única linha da entrada contém dois inteiros L e C, indicando respectivamente o número de linhas e o número de colunas da bandeira. As linhas são numeradas de 1 a L e as colunas são numeradas de 1 a C.

Saída

Seu programa deve escrever na saída a bandeira correspondente à entrada, conforme descrito acima, com L linhas, cada uma contendo C caracteres. Utilize os caracteres . (ponto) e * (asterisco) para desenhar a bandeira.

Restrições

  • 1 ≤ L ≤ 7
  • 1 ≤ C ≤ 7

Exemplos

Entrada
3 3
Saída
...
***
...

Entrada
1 6
Saída
......

Entrada
6 3
Saída
...
***
...
***
...
***

Entrada
1 1
Saída
.

 

 

Avalie este exercício

Flâmula

O partido Radical da Nlogônia planeja uma manifestação de apoio a suas ideias de decentralização administrativa. E quer que todos os manifestantes levem flâmulas do partido.

As flâmulas são triangulares, compostas de N linhas e N colunas de caracteres. Todos os caracteres são asteriscos, representando estrelas da bandeira da Nlogônia. A primeira linha tem N caracteres asterisco, a segunda linha tem um caractere a menos do que a linha anterior, a terceira linha tem um caractere a menos do que a linha anterior, e assim por diante, até a última linha, que tem apenas um caractere asterisco. A figura abaixo mostra três exemplos de flâmulas possíveis:

Na figura, a flâmula mais à esquerda tem N igual a três, a flâmula do meio tem N igual a dois, e a flâmula da direita tem N igual a cinco.

Dado o valor de N, faça um programa para escrever na saída a flâmula correspondente.

Entrada

A primeira e única linha da entrada contém um inteiro N, indicando o número de linhas da flâmula.

Saída

Seu programa deve escrever na saída a flâmula correspondente à entrada, com N linhas. Utilize o caractere * (asterisco) para desenhar a flâmula.

Restrições

  • 1 ≤ N ≤ 7

Exemplos

Entrada
3
Saída
***
**
*

Entrada
5
Saída
*****
****
***
**
*

Entrada
2
Saída
**
*

 

 

Avalie este exercício

Tomates

A Fazenda Fartura tem uma plantação de tomates de formato retangular, sub-dividida em N linhas e M colunas de canteiros quadrados. As linhas são numeradas de 1 a N, e as colunas são numeradas de 1 a M.

A produção de tomates de cada canteiro é registrada ao final de cada safra para que a adubação possa ser melhor distribuída na próxima safra. A figura abaixo mostra um exemplo.

Na figura, é mostrada uma plantação dividida em 3 linhas por 4 colunas de canteiros, em que o canteiro na linha 2 e coluna 4 tem produção de 80 tomates, que é a menor produção da plantação.

Dadas a produção de cada canteiro, faça um programa para determinar a linha e a coluna do canteiro com a menor produção de tomates.

Entrada

A primeira linha da entrada contém dois inteiros N e M, indicando respectivamente o número de linhas e o número de colunas da plantação. Cada uma das N linhas seguintes contém M inteiros, indicando a produção de tomates de um canteiro. Considere que as produções são todas diferentes uma das outras (ou seja, não há empates na produção dos canteiros).

Saída

Seu programa deve escrever na saída uma única linha, contendo dois inteiros, o número da linha e o número da coluna do canteiro com a menor produção, separados por um espaço em branco.

Restrições

  • 1 ≤ N ≤ 10
  • 1 ≤ M ≤ 10
  • 0 ≤ produção de um canteiro ≤ 200
  • Cada canteiro tem uma produção diferente dos demais.

Exemplos

Entrada
2 3
40 50 10  
0 20 30
Saída
2 1

Entrada
1 5
95 100 90 98 99
Saída
1 3

Entrada
1 1
0
Saída
1 1

Entrada
3 4
100 110 122 103
150 112 117 80
108 102 120 115
Saída
2 4

 

 

Avalie esta aula

Soluções para os exercícios

Nesta seção você encontra exemplos de soluções para os exercícios. Mas antes de ver a solução para um exercício tente resolvê-lo, criando a sua própria solução.

Solução do Exercício 1
Solução do Exercício 1
// Solução para o exercício 1, aula 12
// Bandeira mutante

var i, j,  // usados como contadores
    N, M;  // linha e coluna da posição da estrela

scanf("%d%d", "N", "M");
i = 1;
while (i<=3) {
    // para cada linha
    // escreve a linha com um outro comando while
    j = 1;
    while (j<=5) {
        // para cada coluna
	// verifica se é a posição da estrela
        if (i===N && j==M)
            printf("*");
        else
            printf(".");
        j = j + 1;
    }  
    // ao final da linha, escreve caractere final-de-linha
    printf("\n");
    i = i + 1;
}

 

Solução do Exercício 2
Solução do Exercício 2
// Solução para o exercício 2, aula 12
// Bandeira da estrela solitária

var i, j,                // usados como contadores
    N, M,                // número de linhas e de colunas
    lin_meio, col_meio;  // linha e coluna da posição da estrela

scanf("%d%d", "N", "M");
lin_meio=Math.ceil(N/2);
col_meio=Math.ceil(M/2);
i = 1;
while (i<=N) {
    // para cada linha
    // escreve a linha com um outro comando while
    j = 1;
    while (j<=M) {
        // para cada coluna verifica se é a linha e coluna do meio
        if (i===lin_meio && j==col_meio)
            printf("*");
        else
            printf(".");
        j = j + 1;
    }  
    // ao final da linha, escreve caractere final-de-linha
    printf("\n");
    i = i + 1;
}

 

Solução do Exercício 3
Solução do Exercício 3
Uma abordagem para resolver esse problema é usar uma variável para armazenar o caractere a ser escrito. Inicialmente a variável tem o valor "." (a primeira linha deve usar o caractere ponto). Então, a cada final de linha, o valor da variável é alterado. Uma implementação para essa abordagem é mostrada abaixo.
// Solução para o exercício 3, aula 12
// Bandeira radical

var i, j,                // usados como contadores
    N, M,                // número de linhas e de colunas
    carac_linha;         // caractere a ser impresso na linha

scanf("%d%d", "N", "M");
carac_linha = ".";       // primeira linha é de pontos
i = 1;
while (i<=N) {
    // para cada linha
    // imprima uma coluna
    j = 1;
    while (j<=M) {
        // para cada coluna
        // imprimimos um caractere, que pode ser ponto ou asterisco
        printf("%s", carac_linha);
        j = j + 1;
    }
    // ao final da linha, escreve caractere final-de-linha
    // e troca o caractere para a próxima linha
    printf("\n");
    if (carac_linha===".")
        carac_linha = '*';
    else
        carac_linha = '.';
    i = i + 1;
}

Uma outra abordagem para resolver o problema é, antes de escrever cada caractere, verificar se o número da linha é par ou impar. Se for impar, escreve um asterisco, caso contrário escreve um ponto.

Essa abordagem, no entanto, é ligeiramente menos eficiente do que a primeira, pois exige uma comparação a cada caractere, enquanto a primeira abordagem exige uma comparação a cada linha. A primeira abordagem é, portanto, M vezes mais eficiente; no entanto, considerando que o valor de M é muito baixo, de acordo com as restrições do enunciado, isso não é importante neste caso.

Uma implementação com essa abordagem é mostrada abaixo.

// Solução para o exercício 3, aula 12
// Bandeira radical

var i, j,                // usados como contadores
    N, M;                // número de linhas e de colunas

scanf("%d%d", "N", "M");
i = 1;
while (i<=N) {
    // para cada linha
    // escreve a linha com um outro comando while
    j = 1;
    while (j<=M) {
        // para cada coluna
        // verifica se a linha é par ou ímpar
        // e escreve o caractere apropriado
        if ((i % 2) === 0)
            printf("*");
        else
            printf(".");
        j = j + 1;
    }  
    printf("\n");
    i = i + 1;
}

 

Solução do Exercício 4
Solução do Exercício 4

A maneira mais fácil de resolver esse problema é fazer o comando de repetição mais externo (para cada linha) iniciar com o valor de N e ser decrementado a cada passo. Dessa forma o valor do contador do comando de repetição mais externo pode ser usado no comando de repetição mais interno como o número de asteriscos que deve ser impresso na linha corrente.

O programa abaixo implementa essa abordagem.

// Solução para o exercício 4, aula 12
// Flâmula

var i, j,                // usados como contadores
    N;                   // número de linhas e de colunas

scanf("%d", "N");
i = N;
while (i>=1) {
    // para cada linha
    // escreve a linha com um outro comando while
    j = 1;
    while (j<=i) {
        // para cada coluna
        // escreve um asterisco
	printf("*");
        j = j + 1;
    }  
    // ao final da linha, escreve caractere final-de-linha
    printf("\n");
    i = i - 1;          // note que decrementamos o contador
}

 

Solução do Exercício 5
Solução do Exercício 5

A solução envolve encontrar o menor valor entre todos os valores lidos, e tomar o cuidado de armazenar também a linha e a coluna onde o menor valor foi encontrado. Como sabemos que o maior valor possível para um canteiroa é 200, pelas restrições do enunciado, podemos inicializar a variável que vai armazenar o menor valor com 201. Note que não precisamos inicializar os valores das variáveis que guardam a linha e coluna do menor valor.

O programa abaixo implementa essa abordagem.

// Solução para o exercício 5, aula 12
// Tomates

var i, j,                // usados como contadores
    N, M,                // número de linhas e de colunas
    min,                 // minimo valor encontrado
    lmin, cmin,          // linha e coluna do valor mínimo
    x;                   // armazena valor lido

// lê dimensão do canteiro
scanf("%d%d", "N", "M");
min=201;                 // inicializa com um valor maior do que todos que podem ser lidos
i=1;
while (i<=N) {
    // para cada linha
    j = 1;
    while (j <= M) {
        // para cada coluna
        // lê valor e verifica se encontrou menor do que conhece
        scanf("%d","x");
        if (x < min) { // encontrou novo mínimo
            lmin = i;  // armazena linha e coluna correntes
            cmin = j;
            min = x;   // e valor do mínimo corrente
        }
        j = j + 1;
    }
    i = i + 1;
}

// escreve o resultado: linha e coluna do menor valor encontrado
printf("%d %d\n", lmin, cmin);

 

 

 
Área de Trabalho
Entrada
Programa
Saída