Jump to content

Ciclos com break VS Ciclos com boolean


Baderous
 Share

Recommended Posts

O título pode não ser muito esclarecedor mas passo a explicar. Tenho um professor que exige que utilizemos determinadas regras a programar:

- Ciclos for são usados para iterar sobre todos os elementos de um conjunto/colecção/array/wtv.

- Ciclos while e do while são usados com uma condição booleana de paragem e são usados para iterar sobre 0 ou mais elementos de um conjunto/colecção/array/wtv (os que verifiquem a condição).

- Não se deve usar break dentro de for, na tentativa de implementar um while.

Passo a citar:

Note-se que sendo a condição_de_iteração testada antes da primeira execução do corpo, pode acontecer

que, sendo a primeira imediatamente falsa, este não seja executado. Assim, a principal característica

determinante na utilização de uma estrutura repetitiva do tipo while é que a mesma conduz a 0 ou mais

iterações do corpo de instruções a iterar. O número de iterações que serão efectivamente realizadas não pode

nestes casos ser expresso apenas em função dos sucessivos valores tomados por uma variável de controlo.

Quando o número de iterações pode de facto ser expresso de tal forma, a estrutura aconselhada é uma

estrutura repetitiva do tipo for. É, no entanto, curioso verificar que os programadores, por erro conceptual

ou simples hábito que não se aconselha que seja reproduzido, implementam estruturas while através de

estruturas for, quer usando break, quer através de condições adicionais de saída na expressão de

condição_de_saída do ciclo for.

Aconselha-se vivamente que, sempre que pretendermos expressar uma iteração que pode ocorrer 0 ou mais

vezes, se expresse tal facto usando uma estrutura while. Sempre que pretendermos expressar uma iteração

que ocorre tantas vezes quantos os valores que uma dada variável deve tomar para que, qualquer que seja o

incremento, partindo de um dado valor atinja um outro, então, tal deve ser codificado usando uma estrutura

for.

Eu agora pergunto: Qual é a diferença, para além da estética e da parte conceptual, entre usar um for com um break ou usar um while? Penso que a maior diferença será ao nível do código Assembly gerado...

Link to comment
Share on other sites

Julgo que o teu professor diz isso por razões conceptuais.

Mas há situações em que o break/condição extra facilita muito.

Exemplo: Imprimir uma matriz respeitando a seguinte regra: nenhum número numa linha deve ser impresso se tiver sido impresso um 0 nessa linha.

um código como este:

for (int i=0;i<lines;i++) {
  for (int j=0;j<cols;j++) {
    cout << m[i][j] << " ";
    if (!m[i][j]) break;
  }
  cout << endl;
}

Implementar isto com while dá um bocado mais trabalho..

Link to comment
Share on other sites

Não usar break ou goto são velhas "boas práticas de programação", com as quais eu concordo.

Através de condições, consegue-se sempre fazer um programa sem eles e bem estruturado.

Claro que admito que use o break as vezes, mas eu prefiro não usar.

"What we do for ourselves dies with us. What we do for others and the world, remains and is immortal.", Albert Pine

Blog pessoal : contém alguns puzzles, algoritmos e problemas para se resolver com programação.

Link to comment
Share on other sites

Hehe eu vou ser do contra. Eu gosto de usar breaks e continues, obviamente moderadamente. Mas uso bastante para criar algo tipo guardas. Acho que torna o código mais legível e mais facilmente editável a futuras alterações.

Imaginemos que tenho uma colecção de um certo tipo de objectos, e quero os processar de alguma forma conforme certas propriedades dos mesmos. Se há partida não souber que todos os meus elementos respeitam essas propriedades, só tenho duas alternativas:

- Filtrar previamente os elementos obtendo uma sub-colecção dos elementos e então é que vou iterar sobre essa para processar os elementos.

- Itero sobre todos os elementos todas da colecção mas apenas processo os que são válidos.

90% dos casos a segunda abordagem é melhor, já que aplico uma fusão dos loops.

Agora se não formos usar breaks ou continues, o código ficaria algo como:

for(Tipo x; ...) {
  if(condicao1 x || condicao 2 || (condicao3 && condicao4)) {
    O elemento x é válido
    Toda a lógica vai é inserida aqui
    ...
  }
}

Eu pessoalmente não gosto nada disto. Prefiro mais desta forma:

for(Tipo x; ...) {
    if (condicao1 x) continue;
    if (condicao2 x) continue;
    if (condicao3 x && condicao4 x) continue;

    O elemento x é válido
    Toda a lógica vai é inserida aqui
    ...
  }
}

Acho que torna o código mais legível. E qualquer alteração nos "filtros" é muito mais agradável.

Para além que detesto ver blocos de código enormes (reminiscência de Haskell??) e no 1º caso normalmente resulta em blocos de if enormes...

Agora o que eu não percebo é a diferenciação do prof perante os fors e whiles. O for é um while só tem é uma sintaxe mais agradável para o programador.

"Give a man a fish and he will eat for a day; Teach a man to fish and he will eat for a lifetime. The moral? READ THE MANUAL !"

Sign on a computer system consultant's desk

Link to comment
Share on other sites

Acho que torna o código mais legível. E qualquer alteração nos "filtros" é muito mais agradável.

Para além que detesto ver blocos de código enormes (reminiscência de Haskell??) e no 1º caso normalmente resulta em blocos de if enormes...

Para melhorar a legibilidade nesses casos gosto mais de meter uma condição por linha, assim:

for(Tipo x; ...) {
  if(condicao1 x || 
     condicao 2 || 
     (condicao3 && condicao4)
   ) {
      O elemento x é válido
      Toda a lógica vai é inserida aqui
      ...
  }
}

Quanto às questão do for vs while há linguagens (por exemplo php) em que há uma pequena diferença performance e memória utilizada entre os dois loop's, sendo o while o loop mais "leve". No entanto são diferenças mínimas e penso que não se justifica cuidados especiais...

Eu escolho o while ou for em função do problema que tenho para resolver... se tenho de contagem uso o for, se é para testar uma condição uso o while.

Daniel Amorim

VP for xRTML

http://www.xrtml.org http://www.realtime.co

Link to comment
Share on other sites

Então e se for com 2 whiles? 😉 :😛

Penso que assim o trabalho seria o mesmo, embora o for seja mais indicado para o caso 😁

Nunca ponderei implementar só com um..

Mas ficaria algo assim:

int i=0;
while (i<lines) {
  int j=-1;
  do {
    j++;
    cout << m[i][j] << " ";
  } while(m[i][j] && j+1<cols);
  i++;
  cout << endl;
}

Sinceramente, só para não usar um break, este código feio.. Só queremos varrer uma matriz!

Link to comment
Share on other sites

Não obrigatoriamente.

int i=0, j = 0;
while (i<lines) {
  j = 0;
  do {
    cout << m[i][j++] << " ";
  } while(m[i][j] && j+1<cols);
  i++;
  cout << endl;
}

😁

Não peças ajuda por PM! A tua dúvida vai ter menos atenção do que se for postada na secção correcta do fórum!

Link to comment
Share on other sites

Esse programa não chega a imprimir o 0 (a menos que esteja na primeira linha) e vai imprimir números depois dele se estiver na primeira posição.

Não estou a dizer que não é possível fazer mais pequeno sem breaks, mas acho que já demonstrei que HÁ casos em que dá muito jeito.

Link to comment
Share on other sites

Esse programa não chega a imprimir o 0 (a menos que esteja na primeira linha) e vai imprimir números depois dele se estiver na primeira posição.

Não estou a dizer que não é possível fazer mais pequeno sem breaks, mas acho que já demonstrei que HÁ casos em que dá muito jeito.

Não imprime o 0 porquê?

Não peças ajuda por PM! A tua dúvida vai ter menos atenção do que se for postada na secção correcta do fórum!

Link to comment
Share on other sites

Sinceramente, só para não usar um break, este código feio.. Só queremos varrer uma matriz!

Não percebi que estavas a dizer que era sem break.

isso não é válido, nem compila..

Se leste o que estava aqui antes, esquece o que perguntei :😁 Mas a verdade é que compila... O código é válido. Entra é em ciclo infinito... e não pára no 0.

Desaparecido.

Link to comment
Share on other sites

Se leste o que estava aqui antes, esquece o que perguntei :😉 Mas a verdade é que compila... O código é válido. Entra é em ciclo infinito... e não pára no 0.

É verdade  ? aquilo fica a preso no

while(m[i][j])

caso o primeiro elemento não seja 0, assim fica a imprimir 1 até mais não.. ups!

Lembrei-me dessa construção e mandei o código sem pensar bem no assunto...  😁

Daniel Amorim

VP for xRTML

http://www.xrtml.org http://www.realtime.co

Link to comment
Share on other sites

Ele compila porque considera isto

int i = -1, j = -1;


while(++i < lines){		
while(++j < cols ){
	cout << m[i][j] << " ";
}
        while(m[i][j]);
  j = -1;
cout << endl;
}

É-lhe indiferente ter o while na linha de cima ou na de debaixo..

Tiracio: não imprimes o 0 porque estás a: imprimir, incrementar, verificar. Ou seja, verificas antes de imprimir.

Link to comment
Share on other sites

Warrior, a não ser que algo tenha mudado de repente, ele tem i=0, j=0, mostra m[ i][j], incrementa o j, verifica se o próximo está vazio ou não. Logo, imprime o m[0][0].

Não peças ajuda por PM! A tua dúvida vai ter menos atenção do que se for postada na secção correcta do fórum!

Link to comment
Share on other sites

Não estava a falar do m[0][0], mas sim do valor "0" se estiver armazenado a meio da matriz.

Tipo isto:

7 8 9

3 0 4

1 2 3

O teu programa imprime:

7 8 9

3

1 2 3

Quando se falava nisto:

7 8 9

3 0

1 2 3

Já fizemos hijack ao tópico..

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.