Bug do Dia: Algo de Estranho no Do While

De ccppbrasil.org

Acontece com todo mundo: você vai dar manutenção num código que não é seu e de repente descobre que parou de funcionar um pedaço em que você não mexeu...

Neste caso, a raiz do problema me trouxe um sorriso. O programa abaixo contem o engano do programador original, sem as complicações inerentes a um programa real.

#include <stdio.h>

// Le o tipo
int LeTipo (void)
{
  int tipo;

  printf ("Tipo: ");
  scanf ("%d", &tipo);

  return tipo;
}

// Le um item
// (bem bobinho para fim de teste)
void LeItem (int n)
{
  int item;

  printf ("Item %d: ", n+1);
  scanf ("%d", &item);
}

// Determina o numero de itens a ler
int DetQtde (int tipo)
{
  return 3*tipo;	// p/ fins de teste
}

void tela (void)
{
  int nLido, nTotal, tipo;

  tipo = -1;
  nLido = 0;
  do
  {
    if (tipo < 1)
    {
      tipo = LeTipo ();
      if (tipo < 1)
        continue;	// tipo invalido, ler novamente
      nTotal = DetQtde(tipo);
    }
    LeItem (nLido);
    nLido++;
  } while (nLido < nTotal);
}

int main (int argc, char *argv[])
{
  tela ();
}

Você consegue achar o erro?

Dica

O que acontece quando LeTipo retorna um valor menor que 1?

Solução

O programador original pensou que o continue ia retornar para o inicio do loop, logo depois do do. Na verdade, o continue vai para o final do loop, testar a condição do while. Neste momento nTotal ainda não foi iniciado e portanto o resultado é indefinido. Como o programador original era sortudo e eu azarado, só aconteceu de sair fora do loop depois que eu coloquei a mão.

(Selecionar com o mouse para ver o texto)

Ferramentas pessoais