Avvia e chiude le azioni in cicli while

0

A volte trovo utile avere cicli che fanno un'azione all'inizio e / o alla fine di un ciclo while .

Il modo migliore che io possa pensare per rappresentare questo in C ++ sarebbe:

if(condition) {
    // Pre-loop actions.
    while(condition) {
        // Loop actions
    }
    // Post-loop actions.
}

O con un'ottimizzazione goto (in teoria):

if(condition) {
    // Pre-loop actions.
    goto loopStart;
    while(condition) {
            loopStart:
        // Loop actions
    }
    // Post-loop actions.
}

Qualunque linguaggio di programmazione ha una struttura più formale per rappresentarlo? È questa la migliore costruzione strutturale in linguaggi C-like (ad esempio è stata discussa nella letteratura scientifica)?

    
posta Graham 31.07.2018 - 22:57
fonte

3 risposte

1

Non sono sicuro al 100% di capire che tipo di cose stai pensando qui. Un esempio realistico più concreto potrebbe aiutare.

Ma personalmente trovo già abbastanza ragionevole l'esempio che hai fornito in C ++.

Nota anche - c'è un ciclo for in C ++, che si avvicina molto a quello che stai descrivendo.

Da cppreference

for ( init-statement; condition(optional) ; iteration_expression(optional) ) statement

Quindi puoi scrivere:

for (Pre-loop actions; condition; Post-loop actions) {
    // Loop actions
}

Ma qui le azioni pre-loop vengono eseguite anche se la condizione è falsa. E le azioni post-ciclo vengono eseguite ogni volta attraverso il ciclo.

C'è un altro schema che trovo MOLTO utile, a cui potresti pensare, e questo è un blocco "finalmente". Gestisce bene la logica del cleanup after look.

Per esempio vedi uso di esempio di Finally

        [[maybe_unused]] auto&& cleanup = Execution::Finally ([]() noexcept { ::endutxent (); });
        ::setutxent ();
        for (const utmpx* i = ::getutxent (); i != nullptr; i = ::getutxent ()) {
            if (i->ut_type == BOOT_TIME) {
                result.fBootedAt = DateTime (i->ut_tv);
                succeeded        = true;
            }
        }

qui il blocco 'finally' viene dichiarato prima del ciclo, ma fatto in seguito (come andando fuori ambito) - così utile per le attività di pulizia (specialmente nella presenza di eccezioni).

    
risposta data 31.07.2018 - 23:43
fonte
1

Poiché sai già che la condizione del ciclo while è vera quando si incontra per la prima volta il ciclo, puoi cambiarlo in do / while loop:

if(condition) {
    // Pre-loop actions.
    do {
        // Loop actions
    } while(condition);
    // Post-loop actions.
}

In questo modo la condizione non viene ricontrollata fino a quando il ciclo non viene eseguito una volta.

    
risposta data 01.08.2018 - 03:11
fonte
0

Per scrivere loop (diversi da quelli che eseguono l'iterazione per un conteggio specifico), utilizzo una terza opzione, preferendo l'uso del ciclo infinito con break; da qualche parte nel ciclo:

// Pre-loop actions
for (;;) {
    // Pre-condition actions (e.g. prompt or prime)
    if ( ! condition ) 
        break;
    // post-condition actions (e.g. the main loop-body actions)
}
// Post-loop actions

Questo è ASCIUTTO quanto otterrai. L'utilizzo di while spesso richiede che il codice prompt / priming sia duplicato, ad es. una volta fuori dal ciclo e una volta nel ciclo.

Inoltre, questo approccio non duplica il test della condizione. Posso immaginare che in alcuni casi l'intero ciclo debba essere fatto in modo condizionale come stai suggerendo; tuttavia, vorrei che le azioni pre e post loop funzionassero idealmente anche se il ciclo non eseguisse iterazioni effettive; meno logica condizionale, meglio è.

    
risposta data 31.07.2018 - 23:43
fonte

Leggi altre domande sui tag