Questo ha qualche equivalente in c?Resa in C#
risposta
No. Su Windows, tuttavia, è possibile utilizzare le fibre per ottenere un effetto simile.
Fibre? Oh, questo:
Yield Return Iterator per Native C++ con fibre
http://www.codeproject.com/KB/library/fiber-based_iterator.aspx
Mentre C non ha lo stesso concetto di rendimento per quanto riguarda enumerare su un insieme che ha la capacità di creare coroutine e fibre.
Ecco alcuni articoli di Wikipedia, che potrebbero essere di interesse:
http://en.wikipedia.org/wiki/Setcontext http://en.wikipedia.org/wiki/Setjmp/longjmp
Penso che questo è di gran lunga troppo complicato. La metodologia migliore sarebbe quella di creare solo una struct che ha avuto una variabile yieldindex e l'array in esso, quindi incrementare l'indice ogni volta che si farebbe 'rendimento'. In questo modo il tuo "rendimento" tira semplicemente il valore dell'array dal punto yieldindex. – DevinB
Non sto dicendo che non è complicato, solo che questo è il C equivalente. Ci sono molti modi per risolvere questo problema ... per questo scriviamo software =) – jonnii
No. Tuttavia, è possibile ottenere simili effetti in C con l'uso di setjmp, longjmp, ma è molto difficile.
Il rendimento viene implementato dal compilatore come una classe personalizzata che implementa una macchina a stati. Anche se non è possibile ottenere la sintassi con la stessa facilità (a meno che non si utilizzi il metodo fibra specificato in precedenza) è possibile replicare i risultati da soli in modo piuttosto semplice, anche se è piuttosto noioso. Ecco come (vi mostrerò in C#, dovrete fare la cosa appropriata in C++ a seconda del tipo in uso):
Supponendo che il seguente codice:
public IEnumerable<T> GetOddStrings(
IEnumerable<IEnumerable<string>> stringCollections)
{
foreach(var stringCollection in stringCollections)
foreach(var str in stringCollection)
{
if(str.Length %2 != 0) yield return str;
if(str.Length == 42) yield break; // 42 is BAD! Stop immediately
}
}
1) Svolgere tutte foreach metodi in enumeratore esplicito chiamate:
public IEnumerable<T> GetOddStrings(
IEnumerable<IEnumerable<string>> stringCollections)
{
var firstEnumerator = stringCollection.GetEnumerator();
while(firstEnumerator.MoveNext())
{
var secondEnumerator = firstEnumerator.Current.GetEnumerator();
while(secondEnumerator.MoveNext())
{
var str= secondEnumerator.Current;
if(str.Length %2 != 0) yield return str;
if(str.Length == 42) yield break;
}
}
}
2) Spostare tutte le variabili locali alla parte superiore del metodo:
public IEnumerable<T> GetOddStrings(
IEnumerable<IEnumerable<string>> stringCollections)
{
IEnumerator<IEnumerable<string>> firstEnumerator;
IEnumerator<string> secondEnumerator;
string str;
firstEnumerator = stringCollections.GetEnumerator();
while(firstEnumerator.MoveNext())
{
secondEnumerator = firstEnumerator.Current.GetEnumerator();
while(secondEnumerator.MoveNext())
{
str= secondEnumerator.Current;
if(str.Length %2 != 0) yield return str;
if(str.Length == 42) yield break;
}
}
}
3) Passare a un costrutto di loop con un'istruzione switch nidificata.
a) Modificare lo stato e continuare il ciclo per ogni rendimento restituito. b) Invertire se condizioni a c) Interruzione del rendimento per ogni condizione di uscita (di seguito si inverte il valore if).
public IEnumerable<T> GetOddStrings(
IEnumerable<IEnumerable<string>> stringCollections)
{
IEnumerator<IEnumerable<string>> firstEnumerator;
IEnumerator<string> secondEnumerator;
string str;
int state = 0;
while(true)
{
switch(state)
{
case 0:
firstEnumerator = stringCollections.GetEnumerator();
// This could be "yield break" but I want to show how you
// could split ifs with significant code in the else
if(!firstEnumerator.MoveNext())
{
state = 1;
continue;
}
secondEnumerator = firstEnumerator.Current;
if(!secondEnumerator.MoveNext) continue;
state = 2;
if(str.Length %2 != 0) yield return str;
continue;
case 1:
yield break;
case 2:
if(str.Length == 42) yield break;
state = 0;
continue;
}
}
}
4) Spostare in una classe e restituire la classe da metodo: a) le pause di rendimento diventano "return false;" b) i resi di rendimento diventano "this.Current = ??; return true;"
public IEnumerable<T> GetOddStrings(
IEnumerable<IEnumerable<string>> stringCollections)
{
return new OddStringEnumerable(stringCollections);
}
private class OddStringEnumerable : IEnumerable<string>
{
IEnumerable<IEnumerable<string>> stringCollections;
IEnumerator<IEnumerable<string>> firstEnumerator;
IEnumerator<string> secondEnumerator;
string str;
int state;
public OddStringEnumerable(IEnumerable<IEnumerable<string>> stringCollections)
{
this.stringCollections = stringCollections;
}
public string Current { get; private set; }
public bool MoveNext()
{
while(true)
{
switch(state)
{
case 0:
firstEnumerator = this.stringCollections.GetEnumerator();
if(!this.firstEnumerator.MoveNext())
{
this.state = 1;
continue;
}
this.secondEnumerator = this.firstEnumerator.Current;
if(!secondEnumerator.MoveNext) continue;
this.state = 2;
if(str.Length %2 != 0)
{
this.Current = str;
return true;
}
continue;
case 1:
return false;
case 2:
if(str.Length == 42) return false;
this.state = 0;
continue;
}
}
}
}
5) Ottimizzare come appropriato.
Coroutines in C utilizza alcuni hackery del preprocessore, ma implementa un abbastanza naturale (rispetto a qualsiasi altra cosa in C) yield
.
Mentre devi scrivere questo in Python:
"""This is actually a built-in function.
def range(start, stop, step):
i = start
while i < stop:
yield i
i = i + step
"""
if __name__ == '__main__':
import sys
start = int(sys.argv[1]) if len(sys.argv) > 2 else 0
stop = int(sys.argv[2]) if len(sys.argv) > 2 else int(sys.argv[1])
step = int(sys.argv[3]) if len(sys.argv) > 3 else 1
for i in range(start, stop, step):
print i,
print
coroutine.h
vi permette di scrivere questo in C:
#include <coroutine.h>
#include <stdio.h>
int range(int start, int stop, int step) {
static int i;
scrBegin;
for (i = start; i < stop; i += step)
scrReturn(i);
scrFinish(start - 1);
}
int main(int argc, char **argv) {
int start, stop, step, i;
start = argc > 2 ? atoi(argv[1]) : 0;
stop = argc > 2 ? atoi(argv[2]) : atoi(argv[1]);
step = argc > 3 ? atoi(argv[3]) : 1;
while ((i = range(start, stop, step)) >= start)
printf("%d ", i);
printf("\n");
}
$ cc range.c $ ./a.out 10 0 1 2 3 4 5 6 7 8 9
Per qualcosa di più complesso e che richiede rientranza, il Hamming numbers in Python :
def hamming():
yield 1
i2 = (2*x for x in hamming())
i3 = (3*x for x in hamming())
i5 = (5*x for x in hamming())
m2, m3, m5 = i2.next(), i3.next(), i5.next()
while True:
if m2 < m3:
if m2 < m5:
yield m2
m2 = i2.next()
else:
if m2 > m5: yield m5
m5 = i5.next()
elif m2 == m3: m3 = i3.next()
elif m3 < m5:
yield m3
m3 = i3.next()
else:
if m3 > m5: yield m5
m5 = i5.next()
if __name__ == '__main__':
import sys
it = hamming()
for i in range(str(sys.argv[1]) if len(sys.argv) > 1 else 25):
print it.next(),
print
e C:
#include <coroutine.h>
#include <stdio.h>
int hamming(ccrContParam) {
ccrBeginContext;
ccrContext z[3];
int m2, m3, m5;
ccrEndContext(state);
ccrBegin(state);
state->z[0] = state->z[1] = state->z[2] = 0;
ccrReturn(1);
#define m2_next (2*hamming(&state->z[0]))
#define m3_next (3*hamming(&state->z[1]))
#define m5_next (5*hamming(&state->z[2]))
state->m2 = m2_next, state->m3 = m3_next, state->m5 = m5_next;
while (1) {
if (state->m2 < state->m3) {
if (state->m2 < state->m5) {
ccrReturn(state->m2);
state->m2 = m2_next;
} else {
if (state->m2 > state->m5) ccrReturn(state->m5);
state->m5 = m5_next;
}
} else if (state->m2 == state->m3) state->m3 = m3_next;
else if (state->m3 < state->m5) {
ccrReturn(state->m3);
state->m3 = m3_next;
} else {
if (state->m3 > state->m5) ccrReturn(state->m5);
state->m5 = m5_next;
}
}
ccrFinish(-1);
}
int main(int argc, char **argv) {
int count = argc > 1 ? atoi(argv[1]) : 25, i;
ccrContext z = 0;
for (i = 0; i < count; i++)
printf("%d ", hamming(&z));
printf("\n");
}
$ cc hamming.c $ ./a.out 1 2 3 4 5 6 8 9 10 12 15 16 18 20 24 25 27 30 32 36 40 45 48 50 54
in C# rendimenti semplifica la creazione di IEnumberables per una collezione.
In C++ è necessario utilizzare iteratori STL.
- 1. resa Implementazione in C
- 2. C n. Resa in metodo nidificato
- 3. resa condizionale in JSF
- 4. Resa in una funzione ricorsiva
- 5. content_for vs resa in parziali
- 6. Che cos'è la resa ?, e qual è il vantaggio di utilizzare la resa in asp.net?
- 7. Misunderstood pitone resa
- 8. Ricorsione con resa
- 9. Resa F #! operatore - Implementazione ed eventuali equivalenti C#
- 10. implementazione Scala di C# -come resa con "per"
- 11. Dove usare meglio la resa in Python?
- 12. In che modo la resa è enumerabile?
- 13. Resa in vista per più blocchi
- 14. Determina quale vista verrà resa in @RenderBody()
- 15. Differenza tra `resa da foo()` e `for x in foo(): resa x`
- 16. Prestazioni di resa annidata su un albero
- 17. Come funziona questa funzione con una "resa" in dettaglio?
- 18. Ritorno e raccolta iterabile con resa in scala
- 19. carattere Consolas in PyCharm viene resa in un modo strano
- 20. nuova riga in models.TextField() non resa in modello
- 21. Come funziona la resa in codice Python C, parte buona e cattiva
- 22. Resa multipla nel modello di applicazione Meteor.js
- 23. Come funziona questa comprensione lambda/resa/generatore?
- 24. Python: assegnazione di resa e rendimento
- 25. Modifica resa dal valore di ritorno di
- 26. Mappa di Lodash e resa unica
- 27. ndb aysnc "resa successiva" per consumare get_multi_async
- 28. tipo Collection generato da per con resa
- 29. tag docstring per 'resa' parola chiave
- 30. Qual è la resa di Scala?
nemmeno vicino! –
Perché hai bisogno di rendimento? Se si dispone di un array, è possibile solo iterarlo. Il rendimento è rilevante per IEnumerables, che generalmente useresti in una situazione 'foreach'. Dal momento che non puoi "forzare" perché dovresti creare un "rendimento"? – DevinB