2013-02-10 7 views
6

Come dice il titolo, perl aggiunge elementi fittizi agli array dopo richieste a elementi non esistenti. La dimensione della matrice cresce dopo l'inchiesta. Illustrazione per il comportamento:perl aggiunge gli elementi fittizi all'array dopo l'interrogazione

my $rarr; 
    $rarr->[0][0] = 'S'; 
    $rarr->[0][1] = 'MD'; 
    $rarr->[1][0] = 'S'; 
    $rarr->[1][1] = 'PRP'; 

    my $crulesref; 
    $crulesref->[0] = $rarr; 

    check_rule('aa', 0); 
    if($rarr->[3][0] == 'M'){ # just check a not existing element 
     print "m\n"; 
    } 

    check_rule('bb', 0); 
    if($rarr->[5][0] == 'M'){ # again: just check a not existing element 
     print "m\n"; 
    } 
    check_rule('cc', 0); 


    sub check_rule($$) 
    { 
     my ($strg,$ix) = @_; 
     my $aref = $crulesref->[$ix]; 
     my $rule_size = @$aref; 
     {print "-----$strg aref:$aref rs:$rule_size aref:'@$aref'\n"; 
      for(my $t1 = 0; $t1 <$rule_size; $t1++){ 
      print "t1:$t1 0:$aref->[$t1][0] 1:$aref->[$t1][1]\n"; 
      } 
     } 
     } 

Il risultato della corsa è:

[email protected] ~/dtest/perl/forditas/utf8_v1/forditas/test1 $ perl v15.pl 
    -----aa aref:ARRAY(0x90ed8c8) rs:2 aref:'ARRAY(0x9106cac) ARRAY(0x9106d24)' 
    t1:0 0:S 1:MD 
    t1:1 0:S 1:PRP 
    m      <-------------- finds the non existing 
    -----bb aref:ARRAY(0x90ed8c8) rs:4 aref:'ARRAY(0x9106cac) ARRAY(0x9106d24)   ARRAY(0x9107508)' 
    t1:0 0:S 1:MD 
    t1:1 0:S 1:PRP 
    t1:2 0: 1:    <-- undesired dummy due to inquiry 
    t1:3 0: 1:    <-- undesired dummy due to inquiry 
    m      <-------------- finds the non existing 
    -----cc aref:ARRAY(0x90ed8c8) rs:6 aref:'ARRAY(0x9106cac) ARRAY(0x9106d24) ARRAY(0x9107904) ARRAY(0x9107508) ARRAY(0x910e860)' 
    t1:0 0:S 1:MD 
    t1:1 0:S 1:PRP 
    t1:2 0: 1:    <-- undesired dummy due to inquiry 
    t1:3 0: 1:    <-- undesired dummy due to inquiry 
    t1:4 0: 1:    <-- undesired dummy due to inquiry 
    t1:5 0: 1:    <-- undesired dummy due to inquiry 

Non c'è altro modo per evitare questo che chiedere prima di ogni inchiesta, se l'elemento indagato esiste? Cerco di aumentare la velocità e queste richieste rallentano il codice e lo rendono meno facile da leggere.

Grazie in anticipo per suggerimenti utili.

+0

L'individuazione non esistente deriva da una cattiva richiesta. Invece di == è necessario utilizzare l'eq. Tuttavia, questo non è il problema principale. Il problim principale è l'aggiunta di elementi. – eleonora

risposta

12

Questo è autovivification che stai vedendo. Se si accede alla memoria di $ref->[3][0] anche solo con un assegno:

if ($ref->[3][0] eq 'M') 

Poi prima $ref->[3] deve esistere prima del suo numero di elemento zero può essere controllato, in modo che si crea tramite autovivificazione. È necessario innanzitutto verificare se $ref->[3] esiste o è stato definito per evitare di crearlo.

if (defined($ref->[3]) && $ref->[3][0] eq 'M') 

Inoltre, è necessario utilizzare sempre:

use strict; 
use warnings; 

allora si dovrebbe leggere le avvertenze

Argument "M" isn't numeric in numeric eq (==) at ... 
Use of uninitialized value in numeric eq (==) at ... 

I se-clausola dà un falso positivo qui perché la stringa 'M' viene convertito in un numero (0) a causa del contesto imposto dall'operatore di uguaglianza numerica ==. Il valore LHS è undef, che viene anche convertito in un numero (0), motivo per cui l'espressione è true.

+6

'if ($ ref -> [3] && $ ref -> [3] [0] eq 'M')' sarebbe sufficiente – ikegami

+3

@ikegami Sì, ma per motivi di dimostrazione, è forse una buona idea essere specifica. – TLP

+0

Se vuoi davvero essere specifico, sicuramente dovrebbe essere 'if (ref ($ ref -> [3]) eq 'ARRAY' && $ ref -> [3] [0] eq 'M')'. –

Problemi correlati