Pergunta

[EDIT] Whoops houve um erro no código, e agora todas as respostas para a pergunta parece bizarra, mas basicamente o loop for costumava ser, para (i = 0; i <15; i ++). Eu também editado para tornar a questão mais clara. [/ EDIT]

Eu estou tentando fazer um loop, que verifica uma matriz de 16 elementos, de modo que ele faz um loop de 0 a 15. Eu, então, usar a variável i mais tarde, no entanto, por vezes, i == 16, o que causa problemas por estar fora dos limites .

Eu tenho uma solução, mas não parece elegante, o que me faz pensar que eu estou faltando alguma coisa. Eu tentei while, mas eu nunca pode obter qualquer loop para ir de 0 a 15, e nunca terminar em um valor maior do que 15.

Existe alguma maneira de fazer ir loop e verificar todos os 16 elementos da matriz, enquanto nunca ser superior a 15 no final do loop?

int i;

for(i=0; i<16; i++)
{
    someClass.someMethod(i);

    if(someClass.Test())
    {
        break;
    }
}



if (i == 16)
{
    i = 15;
}
Foi útil?

Solução

Eu sugiro usar alguma outra variável que não i após o seu ciclo está terminado. Os critérios de utilização de um loop em vez de um loop while é que você sabe de antemão exatamente quantas vezes um loop será executado. Se você já sabe disso, basta configurar alguma outra variável para o valor final do seu ciclo e usá-lo em vez de dar i um duplo objectivo.

int j = 15;

for(int i=0; i <= j; i++)
{
    someClass.array[i];
}

// continue on using j, which value hasn't changed

Outras dicas

Bem, para começar, seus loops código de exemplo de 0 a 14. Mas se você ciclo de 0 a 15, naturalmente, i tem que ser 16 antes o loop pode acabar. O que acontece é que se torna 16, então o seu ciclo percebe que está fora dos limites e irrompe. Se você quer que acabe em 15, honestamente a melhor coisa a fazer é apenas decréscimo logo após o fim loop.

i é incrementado na última verificação para ser 16, que não inferior a 15 é, por isso, sai do loop com i sendo 16.

Talvez seja útil saber que:

for (before; check; after) { body } 

é o mesmo que:

before 
while(check) { 
  body 
  after 
} 

Se você pensar em seu loop for nesse prazo, talvez você vai descobrir facilmente por isso que eu, na saída, é 16.

Parece haver algumas falhas fundamentais na sua abordagem.

  1. Você realmente não deve usar uma variável de índice fora do âmbito do loop.
  2. Você deve usar uma variável ou função para determinar o limite do loop.
  3. Seria melhor usar iteradores em vez de índices numéricos.
  4. algoritmos genéricos podem eliminar a necessidade de loops.

Apenas meus $ 0,02.

Portanto - se você está verificando uma matriz de 16 elementos, normalmente você faria o seguinte:

for(i=0; i<16; i++)

Como para as obras, é que começa com a primeira declaração de três:

i=0

Em seguida, ele faz o seu check, no segundo declaração:

i < 16 // True here, since 0 < 16

Isso acontece antes de seu loop. Em seguida, ele executa o bloco de seu laço com esse conjunto:

someClass.array[i]; //0

Finalmente, ele faz a declaração final:

i++

Em seguida, repete os segundo e terceiro demonstrações, numa sequência.

Antes da última corrida, eu == 14, então ele faz i ++, estabelecendo i a 15, e executa o bloco. Finalmente, ele faz i ++, estabelecendo:

i==16

Neste ponto, a condição já não é verdade:

i < 16 // False, since i==16

Neste ponto, o bloco não é executado, mas ainda está definido para 16.

Você deve ter perdido alguma coisa.

Neste circuito não seria sequer atingiu 15, você precisa dizer i <= 15, logo que eu = 14 ele tinha executado uma vez e fiança.

O loop for é equivalente ao seguinte ciclo while:

i = 0;
while(i < 16) {
    someClass.array[i];

    i++;
} // while

necessidades i para chegar a 16 para sair do loop corretamente.

Tecnicamente, há maneiras de escrever o loop de tal forma que i é de 15 ao sair do loop, mas você não deve fazê-las:

int i = 0;
while (1) {
    someclass.someMethod(i);
    if (i < 15) {
        i++;
    } else {
        break;
    }
}

Sim, ele faz o que você pedir. Mas o fluxo é horrível.

Você não pode fazer isso com as estruturas de loop internos, e, como disse Bill The Lizard, você provavelmente não quer realmente reutilizar a variável for-loop.

Mas, se você realmente quiser, aqui está uma maneira de fazê-lo. O truque é colocar a condição de loop no meio do loop:

int i = 0;
while (true)
{
    someclass.array[i];
    if (i == 15)
        break;
    ++i;
}

A questão-chave para entender aqui é que existem 17 diferentes respostas para a pergunta "Qual o valor de i faz com que o teste para ter sucesso?". Ou eu posso estar em {0, 1, ..., 15}, ou nenhum valor de i faz com que o teste para ter sucesso, que é denotada por i == 16 neste caso. Então, se eu é restrito a apenas 16 valores, a questão não pode ser respondida.

Há casos legítimos em que você não quer passar o último valor válido. Por exemplo, se você tivesse 256 valores e por algum motivo você tiver apenas um byte para contar com. Ou, como me aconteceu recentemente, que pretende examinar apenas a cada elemento i de uma matriz e a última adição ao seu iterador leva você muito além do fim da matriz. Nestes casos circuito desenrolando é necessária.

No entanto, para este problema seria mais limpo para usar uma bandeira:

bool flag = false;
for (int i = 0; i < 15; ++i) 
{
    someClass.someMethod(i);

    if (someClass.Test())
    {
        flag = true;
        break;
    }
}

Então é claro se ou não o teste nunca conseguiu.

Se o seu ciclo termina natuarally, em vez de com uma pausa, i irá ser 16. Não há nenhuma maneira de evitar isso. Seu código é perfeitamente aceitável se o que você quer é que eu acabar como 15 ou menos:

int i;
for (i=0; i<16; i++) {
    someClass.someMethod(i);
    if (someClass.Test())
        break;
}
if (i == 16)
    i = 15;

Qualquer coisa que muda i 16-15 após o corpo do laço vai fazer:

if (i == 16) i = 15;
i = (i == 16) ? 15 : i;
i = MAX (15,i); /* where MAX is defined :-) */

e assim por diante.

No entanto, que assume que i vai ser usado para algo significativo como uma pós-condição em relação a esse loop. Acho que é raramente o caso, as pessoas tendem a re-inicializar antes re-uso (como um outro para loop).

Além disso, o que está fazendo torna muito difícil (impossível, mesmo) para descobrir como uma pós-condição, wheteher seu ciclo encerrado normalmente ou se é terminada prematuramente devido someClass.Test() retornou verdadeiro para i == 15. Isso significa usar i para fazer nova decisão é cheia de perigos.

A minha pergunta seria: Por você acha que você precisa para deixar i como 15 ou menos

?

Eu estou tentando fazer um loop, que verifica uma matriz de 16 elementos, de modo que laços de 0 a 15. Eu, então, usar o i variável mais tarde, no entanto, por vezes, i == 16, o que provoca problemas por estar fora dos limites.

Você precisa verificar para o caso em seu loop for não quebrar, porque essa informação determina se ou não o que você queria fazer com i é válido.

Há um par de maneiras de fazer isso. Uma é manter o controle do mesmo em um bool, como "foundClass" ou "testSucceeded". Padrão para falsa, então defini-lo como verdadeiro em sua ruptura. Coloque quaisquer usos de i mais tarde na função de "se (foundClass) {}" blocos.

Outra é fazer apenas o que você fez. Embora o seu retorno não parece certo em tudo. Se você estiver configurando i a 15, você está deitado ao seu código e dizendo-lhe que someClass.Test () conseguiu para i == 15, que não é verdade. Evite definir o valor para algo que é errado apenas para que o código não erro mais tarde. É muito melhor para colocar cheques barrancos ao redor do uso real do i mais tarde no código.

for(int i=0; i<17; i++)
{    
  if(i<16)
  {
     someClass.someMethod(i); 
     if(someClass.Test())   
     {        
       break;    
     }
  }
  else if(i==16)
  {
     i=15;
  }
}

Se você diz que tem uma matriz com 16 elementos, você não tem que definir isso, usar a matriz para obter essa informação (não duplicar as informações)

depois, se você deseja obter o último índice novamente usar a matriz para obter essa informação.

for(int i = 0; i < myArray.length; ++i){
       myArray[i].somemethod();
}
// lastindex = myArray.length-1;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top