Pergunta

Eu só descobri ... de novo ... um desperdício bug tempo real como se segue

for (int i = 0; i < length; i++)
{ //...Lots of code 
    for (int j = 0; i < length; j++)
    {
        //...Lots of code 
    }
}

Você notou a frente a i interna que deve ser j? Nem eu Então, de agora em diante eu vou usar:

for (int i = 0; i < length; i++)
{
    for (int i1 = 0; i1 < length; i1++)
    {
    }
}

Quais são suas dicas para enquanto interior e exterior e de laços?

Editar: Obrigado pelas respostas valiosas. Com isto breve resumo das dicas propostas:

  • usar nomes de variáveis ??significativas para as variáveis ??de índice (em vez i uso SomeObjCollectionLength)
  • colocar o conteúdo da espira interna num método separado e chamar esse método proveniente da espira externa
  • quantidade não manejável de linhas de código entre o circuito externo e interno é um sinal forte para o cheiro de código
  • cópia evitar colar e correndo, escrever o índice vars com cuidado

Você pode querer verificar o resumo por LBushkin para o seguinte

  • uso foreach e iterators sempre que possível
  • inicializar as variáveis ??antes de entrar os laços
  • Faça cada loop executar apenas uma função. Evite misturar responsabilidades em um único laço
  • Quando possível, faça seus loops curto o suficiente para ver tudo de uma vez
Foi útil?

Solução

Não use i & j (ou qualquer outra variável única letra) como nomes de índice. Use nomes próprios e você não vai entrar neste tipo de problemas.

Outras dicas

Uma das soluções mais simples e mais limpas é colocar o conteúdo da espira interna num método por isso torna-se:

for (int i = 0; i < length; i++)
{
    DoSomething();
}

private void DoSomething(int outerValue)
{
    for (int i = 0; i < length; i++)
    {
        // Do something else
    }

}

Para mim, o 'cheiro de código' aqui é 'um monte de código'.

Se a quantidade de código nas alças é particularmente grande, a distância entre as alças meios internos e externos que eles não são tão susceptíveis de ser comparados entre si para correcção.

Na verdade, olhando para o início do loop interno em isolamento deve levar a questão à sua atenção, mas tendo a estrutura principal em como seção um pequeno de código possível dá o seu cérebro menos de digerir.

Pode ser possível extrair dos lotes de código 'seções em funções / métodos separados, a fim de reduzir o tamanho da estrutura principal -. Mas isso não pode sempre ser prático

Além disso, eu diria que 'i1' não é uma boa escolha particularmente do nome da variável, como que tende a encorajar 'i2', 'i3' etc, que realmente não levar a código compreensível. Talvez substituindo todas as variáveis ??de loop com algo mais significativo ajudaria a clareza do código, e reduzir as chances do erro original.

Meu conselho superior (em nenhuma ordem particular) para escrever um código melhor loop (muito disso é do excelente livro Code Complete ):

  1. Evite vários pontos de saída para loops.
  2. Use continuar / romper com moderação.
  3. Refactor aninhados laços em rotinas separadas, quando possível.
  4. Use nomes de variáveis ??significativas para fazer loops aninhados legível.
  5. Use foreach () loop, quando possível, em vez de for (i = ...) loops.
  6. Digite o loop de uma única localização. Não salto em um laço com empreendedores de. Ever.
  7. código de inicialização Coloque imediatamente antes do loop.
  8. instruções de inicialização de loop manter com o laço que estejam relacionados a.
  9. Evite reutilizar variáveis ??entre lacetes não aninhados. 10.Limit o escopo de variáveis ??loop-índice para o próprio loop.
  10. Use while (true) para loops infinitos, em vez de for (;;)
  11. Em idiomas que oferecem construções em bloco (por exemplo, '{' e '}') usá-los em vez de recuar para incluir as declarações de um loop. Sim, até mesmo para loops linha única.
  12. Evite laços vazias.
  13. Evite colocar tarefas domésticas no meio de um loop, colocá-los no início e / ou fim vez.
  14. Faça cada loop executar apenas uma função. Evite misturar responsabilidades em um único loop.
  15. Faça condições de rescisão circuito óbvio.
  16. Não macaco com a variável índice de ciclo de um loop for () para torná-lo terminar.
  17. código Evite que depende do valor final do indexador loop.
  18. Considere o uso de contadores de segurança em loops complexos -. Eles podem ser verificados para garantir que o ciclo não executa muitas ou poucas vezes
  19. Usar instruções break, quando possível, para terminar, enquanto loops.
  20. Quando possível, faça seus loops curto o suficiente para ver tudo de uma vez.

Isso é um copy-paste erro, cópia evitar colar.

Como para a sua solução, não é muito melhor. O erro ainda pode escorregar entre toneladas de código. I tendem a usar nomes significativos mesmo para variáveis ??temporárias de loop.

alavancar o seu IDE, em VS, tente usar este: http://msdn.microsoft.com/en-us/library/z4c5cc9b (VS.80) .aspx

Exemplo: digite , em seguida, pressione Tab Tab sucessivamente

Eu vim aqui para ser inteligente e dizer "Eu só escrevê-lo logo na primeira vez". Mas então eu vi o seu exemplo e, bem, eu fiz isso muitas vezes eu mesmo.

Quando você precisa de loops aninhados como essa, a minha única solução é estar alerta e pensar quando você escrever o código.

Sempre que possível, usando iteradores e para cada laços são agradáveis.

Além disso, eu não posso ver como sua solução sugerida vai ser melhor. E não fica tão agradável também.

Em primeiro lugar, reduzir o tamanho do corpo do ciclo, isto é, material movimento para funções separadas. Em geral, é uma má idéia ter funções mais do que aquilo que pode caber na tela, então laços deve ser ainda menor.

Em segundo lugar, usar nomes de variáveis ??significativas em casos como este. Só usaria i e j em laços simples com poucas linhas de código. Por exemplo, se você está passando por uma matriz bidimensional, "col" e "linha" faria muito mais sentido, tornar o código mais fácil de ler ( "qual era qual?") E mais fácil de detectar erros como este.

Você apenas tem que tomar cuidado extra de tais questões, não há nenhuma bala mágica contra isso. Mesmo com "melhor nomenclatura" que propõe que você vai de vez em quando o controle perde se este é Nth ou (N + M) th nível de loop aninhado e fazer um erro.

Se loop aninhado é escrita necessária-lo com cuidado. Se ele pode ser evitado por meio da extração do corpo loop externo para uma função que seria um bom guarda contra índices de mau uso.

Eu uso e 'jj' 'ii' para contadores de loop transitórios se eu realmente precisa deles - eles são mais fáceis de procurar que 'i' e 'j' e também mais fácil de detectar, em exemplos como o acima. Para sair um pouco melhor que você pode realmente usar um nome de variável real. Se você está looping sobre uma corda, então você pode chamá-lo characterIndex ou algo assim. É mais de digitação, mas documenta-se e economiza tempo na depuração de problemas obscuros mais tarde.

Melhor ainda seria evitar contadores numéricos e usar iteradores nomeados através de uma coleção. Eles tornar mais clara a intenção, na minha opinião.

Finalmente, se possível, é bom para acabar com o ciclo completo: boost :: Foreach é uma maneira de fazer isso em C ++, embora eu geralmente preferem linguagens uso, tais como Python que permitem nativamente iteração direta sobre o conteúdo de um recipiente sem a necessidade de incrementar um valor de índice ou iterator.

Tente usar construções de laço mais declarativas. Por exemplo, se você realmente não precisa de índices (aqueles is e js) e seu ambiente de programação permite-lo, você pode usar uma construção foreach para iterar sobre a coleção.

Como neste como em muitas coisas, há alguns excelentes conselhos em Code Complete de Steve McConnell. Seria bem vale o seu tempo para ler o que ele tem a dizer sobre a construção de um bom código looping. Eu não tenho o meu exemplar do livro acessível aqui, mas todo o livro vale o seu tempo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top