Iniciante para problema de loop
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;
}
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.
- Você realmente não deve usar uma variável de índice fora do âmbito do loop.
- Você deve usar uma variável ou função para determinar o limite do loop.
- Seria melhor usar iteradores em vez de índices numéricos.
- 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;