Pergunta

Eu gostaria de incrementar duas variáveis ??em uma condição for-circuito em vez de um.

Então, algo como:

for (int i = 0; i != 5; ++i and ++j) 
    do_something(i, j);

O que é a sintaxe para isso?

Foi útil?

Solução

A expressão comum é utilizar o vírgula operador que avalia os dois operandos, e retorna o segundo operando. Assim:

for(int i = 0; i != 5; ++i,++j) 
    do_something(i,j);

Mas é realmente um operador vírgula?

Agora, tendo escreveu que, um comentarista sugeriu que era, na verdade, um pouco de açúcar especial sintática na instrução for, e não um operador vírgula em tudo. Eu verifiquei que, em GCC da seguinte forma:

int i=0;
int a=5;
int x=0;

for(i; i<5; x=i++,a++){
    printf("i=%d a=%d x=%d\n",i,a,x);
}

Eu estava esperando x para pegar o valor original de um, por isso deve ter exibido 5,6,7 .. para x. O que eu obtive era esta

i=0 a=5 x=0
i=1 a=6 x=0
i=2 a=7 x=1
i=3 a=8 x=2
i=4 a=9 x=3

No entanto, se eu colchetes a expressão para forçar o analisador para realmente vendo um operador de vírgula, eu recebo este

int main(){
    int i=0;
    int a=5;
    int x=0;

    for(i=0; i<5; x=(i++,a++)){
        printf("i=%d a=%d x=%d\n",i,a,x);
    }
}

i=0 a=5 x=0
i=1 a=6 x=5
i=2 a=7 x=6
i=3 a=8 x=7
i=4 a=9 x=8

Inicialmente eu pensei que este mostrou que não estava se comportando como um operador vírgula em tudo, mas como se vê, esta é simplesmente uma questão de precedência - o operador vírgula tem a menor possível precedência , de modo que a expressão x = i ++, uma ++ é eficazmente analisado como (x = i ++), a ++

Obrigado por todos os comentários, foi uma experiência de aprendizagem interessante, e eu tenho usado C por muitos anos!

Outras dicas

Tente este

for(int i = 0; i != 5; ++i, ++j)
    do_something(i,j);

Tente não fazê-lo!

De http://www.research.att.com/~bs/JSF-AV-rules.pdf :

Rule AV 199
A expressão de incremento em um loop irá executar qualquer acção excepto para alterar uma única parâmetro loop para o próximo valor para o loop.

Justificativa: legibilidade.

for (int i = 0; i != 5; ++i, ++j) 
    do_something(i, j);

Eu vim aqui para me lembrar como codificar um segundo índice na cláusula incremento de um loop for, que eu sabia que poderia ser feito, principalmente, de observá-la em uma amostra que eu incorporado em outro projeto, que escrito em C ++.

Hoje, eu estou trabalhando em C #, mas eu tinha certeza de que iria obedecer às mesmas regras a este respeito, uma vez que a instrução FOR é uma das mais antigas estruturas de controle em toda a programação. Felizmente, eu tinha recentemente passou vários dias documentando precisamente o comportamento de um loop para em um dos meus programas em C mais velhos, e eu rapidamente percebeu que esses estudos lições que aplicadas ao problema de hoje C # decidiu, nomeadamente ao comportamento da segunda variável índice .

Para os incautos, a seguir é um resumo das minhas observações. Tudo o que eu vi acontecendo hoje, observando cuidadosamente variáveis ??na janela Locals, confirmou a minha expectativa de que um C # PARA comporta declaração exatamente como um C ou C ++ instrução FOR.

  1. A primeira vez que um PARA executa loop, a cláusula de incremento (dia 3 de seus três) é ignorada. No Visual C e C ++, o incremento é gerado como três instruções máquina no meio do bloco que implementa o circuito, de modo que o passo inicial é executado o código de inicialização apenas uma vez, em seguida salta sobre o bloco de incremento para executar o teste de terminação. Este implementa o recurso que uma PARA executa loop de zero ou mais vezes, dependendo do estado de suas variáveis ??de índice e limite.
  2. Se o corpo das executa ciclo, a sua última declaração é um salto para o primeiro dos três instruções de incremento que foram ignorados pela primeira iteração. Após estes executar, controlar naturalmente cai o código de teste limite que implementa a cláusula meio. O resultado desse teste determina se o corpo das PARA executa loops, ou se as transferências de controle para a próxima instrução além do salto na parte inferior do seu âmbito.
  3. Uma vez que as transferências de controle da parte inferior do bloco de loop para o bloco de incremento, a variável índice é incrementado antes do teste é executado. Não só este comportamento explica por que você deve codificar suas cláusulas limite da maneira que você aprendeu, mas afeta qualquer incremento secundário que você adicionar, via o operador vírgula, porque se torna parte da terceira cláusula. Por isso, não é alterado na primeira iteração, mas é na última iteração, que nunca executa o corpo.

Se qualquer de suas variáveis ??índice permanece em escopo quando as extremidades de loop, o seu valor será um maior do que o limite que interrompe o loop, no caso da variável índice de verdade. Da mesma forma, se, por exemplo, a segunda variável é inicializado para zero antes de o circuito é inserida, o seu valor no fim será a contagem de iteração, assumindo que é um incremento (++), e não um decremento, e que nada em o corpo do laço muda o seu valor.

Eu concordo com squelart. Incrementando duas variáveis ??é erro propenso, especialmente se você único teste para um deles.

Esta é a maneira legível para fazer isso:

for(int i = 0; i < 5; ++i) {
    ++j;
    do_something(i, j);
}

laços For são destinados a casos em que as corridas de circuito em um aumento / diminuição variável. Para qualquer outra variável, alterá-lo no loop.

Se você precisa j ser amarrado a i, por que não deixar a variável original como está e adicionar i?

for(int i = 0; i < 5; ++i) {
    do_something(i,a+i);
}

Se a sua lógica é mais complexa (por exemplo, você precisa monitorar realmente mais de uma variável), eu usaria um loop while.

int main(){
    int i=0;
    int a=0;
    for(i;i<5;i++,a++){
        printf("%d %d\n",a,i);
    } 
}

Use Matemática. Se as duas operações dependem matematicamente na iteração do loop, por que não fazer a matemática?

int i, j;//That have some meaningful values in them?
for( int counter = 0; counter < count_max; ++counter )
    do_something (counter+i, counter+j);

Ou, mais especificamente referindo-se ao exemplo do OP:

for(int i = 0; i != 5; ++i)
    do_something(i, j+i);

Especialmente se você está passando para uma função por valor, então você deve obter algo que faz exatamente o que você quer.

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