Domanda

Vorrei incrementare due variabili in una condizione -loop for anziché una.

Quindi qualcosa del tipo:

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

Qual è la sintassi per questo?

È stato utile?

Soluzione

Un linguaggio comune è usare operatore virgola che valuta entrambi gli operandi e restituisce il secondo operando. Così:

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

Ma è davvero un operatore virgola?

Ora, dopo averlo scritto, un commentatore ha suggerito che in realtà era uno zucchero sintattico speciale nell'istruzione for e non un operatore virgola. L'ho verificato in GCC come segue:

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);
}

Mi aspettavo che x prendesse il valore originale di a, quindi avrebbe dovuto visualizzare 5,6,7 .. per x. Quello che ho ottenuto è stato questo

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

Tuttavia, se ho messo tra parentesi l'espressione per forzare il parser a vedere davvero un operatore virgola, ottengo questo

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

Inizialmente pensavo che questo mostrasse che non si stava comportando affatto come un operatore virgola, ma a quanto pare, questo è semplicemente un problema di precedenza: l'operatore virgola ha il la precedenza più bassa possibile , quindi l'espressione x = i ++, a ++ viene effettivamente analizzata come (x = i ++), a ++

Grazie per tutti i commenti, è stata un'esperienza di apprendimento interessante e uso C da molti anni!

Altri suggerimenti

Prova questo

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

Cerca di non farlo!

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

  

Regola AV 199
  L'espressione dell'incremento in un ciclo for non eseguirà alcuna azione se non quella di cambiare un singolo   parametro loop al valore successivo per il loop.

     

Motivazione: Leggibilità.

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

Sono venuto qui per ricordare a me stesso come codificare un secondo indice nella clausola di incremento di un ciclo FOR, che sapevo potesse essere fatto principalmente osservandolo in un campione che ho incorporato in un altro progetto, scritto in C ++.

Oggi sto lavorando in C #, ma ero sicuro che avrebbe obbedito alle stesse regole in questo senso, poiché l'istruzione FOR è una delle strutture di controllo più antiche di tutta la programmazione. Per fortuna, di recente ho trascorso diversi giorni a documentare con precisione il comportamento di un ciclo FOR in uno dei miei programmi C più vecchi, e ho capito rapidamente che quegli studi contenevano lezioni che si applicavano al problema C # di oggi, in particolare al comportamento della seconda variabile indice .

Per gli incauti, di seguito è riportato un riepilogo delle mie osservazioni. Tutto ciò che ho visto accadere oggi, osservando attentamente le variabili nella finestra Locals, ha confermato la mia aspettativa che un'istruzione C # FOR si comporti esattamente come un'istruzione C o C ++ FOR.

  1. La prima volta che viene eseguito un ciclo FOR, la clausola di incremento (la terza delle sue tre) viene ignorata. In Visual C e C ++, l'incremento viene generato come tre istruzioni macchina nel mezzo del blocco che implementa il ciclo, in modo che il passaggio iniziale esegua il codice di inizializzazione una sola volta, quindi salta sul blocco di incremento per eseguire il test di terminazione. Questo implementa la funzione che un ciclo FOR esegue zero o più volte, a seconda dello stato del suo indice e delle variabili limite.
  2. Se il corpo del ciclo viene eseguito, la sua ultima istruzione è un salto alla prima delle tre istruzioni di incremento che sono state ignorate dalla prima iterazione. Dopo l'esecuzione, il controllo rientra naturalmente nel codice di test limite che implementa la clausola centrale. Il risultato di quel test determina se il corpo del ciclo FOR viene eseguito o se il controllo viene trasferito all'istruzione successiva oltre il salto nella parte inferiore del suo ambito.
  3. Poiché i controlli vengono trasferiti dalla parte inferiore del blocco di ciclo FOR al blocco di incremento, la variabile indice viene incrementata prima dell'esecuzione del test. Questo comportamento non solo spiega perché è necessario codificare le clausole limite nel modo in cui è stato appreso, ma influisce su qualsiasi incremento secondario che si aggiunge, tramite l'operatore virgola, perché diventa parte della terza clausola. Quindi, non è cambiato nella prima iterazione, ma è nell'ultima iterazione, che non esegue mai il corpo.

Se una delle variabili dell'indice rimane nell'ambito al termine del ciclo, il loro valore sarà uno superiore alla soglia che arresta il ciclo, nel caso della variabile indice reale. Allo stesso modo, se, ad esempio, la seconda variabile viene inizializzata a zero prima che il ciclo venga inserito, il suo valore alla fine sarà il conteggio dell'iterazione, supponendo che sia un incremento (++), non un decremento, e che nulla in il corpo del loop cambia il suo valore.

Sono d'accordo con squelart. L'incremento di due variabili è soggetto a bug, soprattutto se si verifica solo una di esse.

Questo è il modo leggibile per farlo:

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

?? For sono pensati per i casi in cui il loop viene eseguito su una variabile crescente / decrescente. Per qualsiasi altra variabile, modificala nel ciclo.

Se hai bisogno di j per essere legato a i , perché non lasciare la variabile originale così com'è e aggiungere i ?

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

Se la tua logica è più complessa (ad esempio, devi effettivamente monitorare più di una variabile), userei un ciclo mentre .

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

Usa matematica. Se le due operazioni dipendono matematicamente dall'iterazione del loop, perché non fare i calcoli?

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

O, più specificamente facendo riferimento all'esempio del PO:

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

Soprattutto se stai passando a una funzione in base al valore, dovresti ottenere qualcosa che fa esattamente quello che vuoi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top