2015-06-26 10 views
5

Ho bisogno di elaborare il valore di hash dipende dal tipo di valore. Ecco il codice con il problema:Come gestire il tipo di valore hash in Perl XS

I32 keys = hv_iterinit(hash); 
for (I32 i = 0; i < keys; i++) 
{ 
    char *key = NULL; 
    I32 key_length = 0; 
    SV *value = hv_iternextsv(hash, &key, &key_length); 
    // SvROK(value); 
    if (SvTYPE(SvRV(value)) < SVt_PVAV) 
    { 
    // handle scalar 
    printf("key %s has scalar value\n", key); 
    } 
    else if (SvTYPE(SvRV(value)) == SVt_PVAV) 
    { 
    // handle array 
    printf("key %s has array value\n", key); 
    } 
    else if (SvTYPE(SvRV(value)) == SVt_PVHV) 
    { 
    // handle hash 
    printf("key %s has hash value\n", key); 
    } 
} 

Se non utilizzo la riga commentata, ho problemi con i valori scalari. Per esempio con i seguenti hash {a => "b", c => {d => "e"}} è produrre output:

key c has hash value 
key d has scalar value 

Così qui sono le mie domande:

  1. dobbiamo sempre riferimento tornati da hv_iternextsv() o, talvolta restituisce scalare?
  2. Perché non vedo l'output del valore scalare per la chiave a.
Aggiornamento

.

Il mio errore è stato nel funzionamento con il risultato di hv_iternextsv(). Stavo pensando che è sempre un riferimento. Codice Ecco come lavora assomiglia:

I32 keys = hv_iterinit(hash); 
for (I32 i = 0; i < keys; i++) 
{ 
    char *key = NULL; 
    I32 key_length = 0; 
    SV *value = hv_iternextsv(hash, &key, &key_length); 
    if (!SvROK(value)) 
    { 
    // handle scalar 
    } 
    else 
    { 
    if (SvTYPE(SvRV(value)) == SVt_PVAV) 
    { 
     // handle array 
    } 
    else if (SvTYPE(SvRV(value)) == SVt_PVHV) 
    { 
     // handle hash 
    } 
    } 
} 
+0

mi aspetto il vostro pasta mancano alcune parentesi, perché non verrà compilato. Forse vuoi dire: 'if (SvTYPE (SvRV (value)) == SVt_PVAV)'? – LeoNerd

+0

Codice aggiornato, grazie. –

+0

@ikegami Ho aggiornato la mia domanda. Problema che non vedo l'output del valore scalare per la chiave 'a'. –

risposta

3

dobbiamo sempre riferimento restituito da hv_iternextsv() o talvolta restituisce scalare?

Restituisce sempre uno scalare. I valori di hash possono essere solo scalari. Questi scalari possono essere riferimenti ($h{x} = [];), ma non è necessario ($h{y} = 123;).

Perché non vedo l'output del valore scalare per la chiave a.

Non c'è modo la vostra potrebbe forse tornare quello che hai detto che fa, visto che il vostro hash non ha alcuna chiave denominata d. Per l'hash che hai fornito, il codice emette il seguente:

key a has scalar value 
key c has hash value 

Ma è più di una coincidenza di ogni altra cosa che avete ottenuto la risposta giusta. SvTYPE(SvRV(value)) quando value non è un riferimento ??? Non ha senso! Il codice fissa segue:

use strict; 
use warnings; 

use Inline C => <<'__EOI__'; 

    void print_keys(HV* hash) { 
    char *key; 
    I32 key_length; 
    SV *value; 

    hv_iterinit(hash); 
    while (value = hv_iternextsv(hash, &key, &key_length)) { 
     if (SvROK(value)) { 
     SV * const referenced = SvRV(value); 
     if (SvTYPE(referenced) == SVt_PVAV) { 
      printf("The value at key %s is reference to an array\n", key); 
     } 
     else if (SvTYPE(referenced) == SVt_PVHV) { 
      printf("The value at key %s is a reference to a hash\n", key); 
     } 
     else { 
      printf("The value at key %s is a reference\n", key); 
     } 
     } else { 
     printf("The value at key %s is not a reference\n", key); 
     } 
    } 
    } 

__EOI__ 

print_keys({a => "b", c => {d => "e"}}); 

uscita:

The value at key a is not a reference 
The value at key c is a reference to a hash 
+0

Aggiornato la mia risposta. – ikegami

+0

Io chiamo di nuovo quel codice per l'hash, quindi produce quell'output. Ho aggiunto un controllo di riferimento e mostra che il valore per la chiave 'a' non è un riferimento.Quindi la mia seconda domanda è ancora valida. –

+0

Non mentire. È stato risposto, ma l'hai cambiato un'ora dopo. Se hai una nuova domanda, chiedi nei commenti o come una domanda appropriata. // Puoi controllare il tipo di scalare usando 'SvTYPE', ma perché vorresti farlo. Se vuoi una stringa, usa "SvPVutf8'. Se vuoi un intero, usa 'SvIV', ecc. Non ti interessa sapere come è memorizzato. – ikegami

Problemi correlati