2012-05-22 1 views
5
$a=array('a','b','c','d'); 

while(key($a)!==NULL){ 
    echo key($a).'=>'.current($a).'<br/>'; 
    next ($a); 
} 

prev($a); 
var_dump(current($a)); 

Dlaczego var_dump powrót false zamiast "d"?php wskaźnik tablicy kuriozum

+0

Zgaduję kiedyś odejdziesz pat koniec tablicy prev nie będzie już działać.. Nie jestem tego pewien. – Corbin

+0

@Corbin Oczekuję, że masz rację, chociaż nie jest to zaskakujące, że twórcy PHP nie wspomnieli o tym w dokumentacji ... – Alnitak

Odpowiedz

4

To zdecydowanie za projekt, a choć ja czesane przez PHP dokumentacja, nie mogę znaleźć odniesienia do faktu, że po unieważnieniu wskaźnika za pomocą po końcu tablicy nie można już używać prev, kod źródłowy PHP (zend_hash.c) wyjaśnia, co się dzieje:

ZEND_API int zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos) 
{ 
    HashPosition *current = pos ? pos : &ht->pInternalPointer; 

    IS_CONSISTENT(ht); 

    if (*current) { 
     *current = (*current)->pListNext; 
     return SUCCESS; 
    } else 
     return FAILURE; 
} 

ZEND_API int zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos) 
{ 
    HashPosition *current = pos ? pos : &ht->pInternalPointer; 

    IS_CONSISTENT(ht); 

    if (*current) { 
     *current = (*current)->pListLast; 
     return SUCCESS; 
    } else 
     return FAILURE; 
} 

Jak widać, zend_hash_move_backwards_ex (który w PHP, są odwzorowywane na prev) testy czy obecny wskaźnik jest ważny zanim cokolwiek, a zend_hash_move_forward_ex ustawi wartość pListNext który zamierza być null w przypadku ostatniego elementu.

tj przeciwieństwie można się spodziewać, next i prev nie tylko ślepo zwiększyć lub zmniejszyć wskaźnik C następnie sprawdzić wynik zwraca wartość lub NULL, faktycznie sprawdzić wskaźnik przed inkrementacji lub zmniejszanie.

To jest zdecydowanie wadliwa dokumentacja i na pewno musi być udokumentowana. Jak wspomniano w innej odpowiedzi, możesz użyć end, aby przejść do ostatniego elementu po unieważnieniu wskaźnika przez zapętlenie na liście.

Jednak powinieneś być w stanie zaimplementować odpowiednią logikę (bez konieczności używania end()) przez klonowanie wskaźnika przed każdym postępem, a następnie użycie sklonowanego wskaźnika po dotarciu do końca tablicy. (ale nie ma naprawdę dobrego powodu, aby to zrobić, jeśli wiesz już, że prev() jest zepsute przez projekt pod względem nawigacji wstecz już przetestowanej tablicy)

(Poza tematem: Cieszę się, że mogę zobaczyć szanowaną tradycję PHP korzystania inconsistentfunction names żyje i ma się dobrze nawet w bazowego kodu C: zend_hash_move_forward_ex vs zend_hash_move_backward*s*_ex)

0
$a=array('a','b','c','d'); 

while(key($a)!==NULL){ 
    echo key($a).'=>'.current($a).'<br/>'; 
    next ($a); 
} 

prev($a); 
var_dump(current($a)); 

w tym kodzie obok wrócić następną wartość i przejść do następnego punktu i na koniec pętli daje ostatni element, ale wskaźnik przejścia do następnego tj null. dzięki czemu var_dump(current($a)); retunrs false

ale

$a=array('a','b','c','d'); 

while(key($a)!==NULL){ 
    echo key($a).'=>'.current($a).'<br/>'; 
    next ($a); 
} 

//prev($a); 
end(($a); 
var_dump(current($a)); 

będzie uzyskać pożądany pierwiastek D, gdyż wskazuje na ostatnim elemencie d

+0

Myślę, że OP zdaje sobie z tego sprawę, prawdziwym pytaniem jest dlaczego nie możesz użyć 'prev' po' next' osiąga koniec tablicy. –

+0

Wyjaśniłem, dlaczego otrzymuje fałszywą wartość –