2010-08-02 17 views
14

Ho letto che l'uso di strlen è più costoso di tale sperimentazione in questo modo:L'utilizzo di strlen() nella condizione del ciclo è più lento del semplice controllo del carattere null?

Abbiamo una lunga stringa x 100 caratteri.

penso che

for (int i = 0; i < strlen(x); i++) 

è più costoso di questo codice:

for (int i = 0; x[i] != '\0'; i++) 

E 'vero? Forse il secondo codice non funzionerà in alcune situazioni, quindi è meglio usare il primo?

Sarà meglio con il sotto?

for (char *tempptr = x; *tempptr != '\0'; tempptr++) 
+3

il secondo ciclo esegue approssimativamente ciò che 'strlen' fa internamente; Non vedo ancora il punto della domanda –

+1

Scrivilo e testalo. Le metriche sono il modo migliore per sapere quale è meglio. –

+0

Se devi dedicare tempo e sforzi a preoccuparti di cose come questa, potresti risparmiare denaro acquistando un computer più veloce. –

risposta

26
for (int i=0;i<strlen(x);i++) 

Questo codice chiama strlen(x) ogni iterazione. Quindi se x è la lunghezza 100, strlen(x) verrà chiamato 100 volte. Questo è molto costoso. Inoltre, strlen(x) sta iterando su x ogni volta come fa il ciclo for. Questo rende la complessità di O (n^2).

for (int i=0;x[i]!='\0';i++) 

Questo codice non chiama funzioni, quindi sarà molto più rapido rispetto all'esempio precedente. Dal momento che itera attraverso il ciclo solo una volta, è O (n) complessità.

+0

Anche se non c'è niente di corretto nella risposta, ancora non vi è alcun punto di confronto tra le due versioni in quanto non sono due versioni diverse dello stesso algoritmo. Sono solo due codici di esempio che fanno cose diverse –

+0

Entrambi aggiungono 1 a 'i' per ogni carattere nella stringa. Oltre a ciò è un po 'difficile da dire, dal momento che il codice all'interno del ciclo non è stato fornito. – MatthewD

+0

+ 1 per indicare che 'strlen()' viene chiamato ogni volta che viene eseguito il ciclo FOR, quando restituisce lo stesso valore tutte le volte. – kiamlaluno

11

La prima lunghezza codice controlla di x in ogni iterazione di i e richiede O (n) per trovare l'ultimo 0, in modo che richiede O (n^2), il secondo caso è O (n)

+0

così le persone stanno felicemente votando perché O (n^2)> O (n)? ;) –

+0

@Gregory Pakosz per favore mi aiutano perché non so bene la differenza tra loro, quindi perché così arrabbiato? Sono felice perché non mi aiutano a causa di upvoting –

+0

Non sono arrabbiato, ti sto aiutando facendoti realizzare la tua domanda non è una vera domanda e quindi questa non è una "vera risposta" anche se non c'è nulla di sbagliato in ciò che @Artyom ha detto –

2

Posso supporre che nella prima variante trovi strlen ogni iterazione, mentre nella seconda variante non lo fai.
Prova questo per verificare:

int a = strlen(x); 
for (int i = 0; i < a; i++) {...} 
2

Se non c'è nessuna ottimizzazione compilazione. Sì, perché strlen eseguirà iterazioni su ogni byte della stringa ogni volta e la seconda implementazione lo farà una sola volta.

2

immagino il compilatore potrebbe ottimizzare (controllare Gregory Pakosz commenti) per il vostro primo ciclo in modo che si sarebbe in questo modo:

int len = strlen(x); 
for (int i = 0; i < len; i++) 

che è ancora O(n).

In ogni caso, penso che il tuo secondo ciclo for sarà più veloce.

+0

sì, ma 2 * O (n), mentre il secondo è 1 * O (n). – falstro

+3

Il compilatore non può spostare la chiamata strlen() fuori dal ciclo a meno che non sappia che strlen() non ha effetti collaterali e che la lunghezza della stringa non può cambiare all'interno del ciclo. – JeremyP

+2

in realtà GCC può ottimizzare 'strlen' out of the loop perché è riconosciuto come funzione built-in, vedi http://ridiculousfish.com/blog/archives/2010/07/23/will-it-optimize/ –

0

Naturalmente il primo richiederà più tempo del secondo. In realtà non fanno la stessa cosa - il primo sta calcolando la lunghezza della stringa ogni volta; il secondo è (efficacemente) farlo solo una volta.

La prima versione è equivalente a questo: "è più efficiente di chiamare uno strlen biblioteca() che per implementare il mio"

for (int i=0; x[i] != 0; i++) 
    for (int j=0; j<i; j++) 
    ; 

Forse volevi dire La risposta a questo è, ovviamente, "dipende". Il tuo compilatore potrebbe avere versioni intrinseche di strlen() che sono ottimizzate oltre ciò che ti aspetti dalla fonte, potresti trovarti su una piattaforma su cui le chiamate di funzione sono costose (raro oggigiorno), ecc.

L'unica risposta che è sia generale e corretto è "profilo e scopri".

4

Sì, il secondo potrebbe non funzionare il 100% percento delle volte, ma sarebbe abbastanza leggero. Questo perché quando si utilizza strlen() è necessario chiamare il metodo ogni volta. Un modo migliore sarebbe come

int strLength = strlen(x); 
for (int i = 0; i < strLength; i++) 

Spero che questo aiuti.

+1

Affascinante. Qual è lo scenario che hai in mente in cui la seconda versione non funziona, ma la prima? (Supponendo che il contenuto del loop elided non contenga ulteriori modifiche di 'i' o della stringa.) –

+2

@john, se il corpo del loop cambia la lunghezza della stringa ... – mb14

+0

ad esempio, prendi la stringa "il mondo è il migliore" per quanto riguarda ""? –

0

Vale la pena notare che è possibile aprirsi ai problemi di overflow del buffer se non si verifica anche l'indice rispetto alla dimensione del buffer contenente la stringa. A seconda di cosa stai facendo con questo codice, questo può o non può essere un problema pratico, ma raramente fa male avere controlli extra, ed è una buona abitudine entrare.

Io suggerirei: for (i = 0; i < buf_size & & x [i] = '\ 0'; i ++!)

Dove:

  • buf_size è il predeterminato dimensione del buffer. Se x è un array, questo sarà sizeof(x); se x è un puntatore, è necessario avere la dimensione del buffer disponibile.
  • Ho rimosso la dichiarazione di i dal ciclo perché è valida solo per il 99. Se stai compilando solo sotto il 99, sentiti libero di reinserirlo.
Problemi correlati