2015-06-26 72 views
5

我需要处理哈希值取决于值类型。这里是有问题的代码:如何在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); 
    } 
} 

如果我不使用注释行,我有标量值的问题。例如具有以下哈希{a => "b", c => {d => "e"}}是产生输出:

key c has hash value 
key d has scalar value 

因此,这里是我的问题:

  1. 难道我们总是从hv_iternextsv()返回的引用,有时它返回标?
  2. 为什么我看不到关键字a的标量值输出。

更新。

我的错误是与hv_iternextsv()的结果一起工作。我在想这总是一个参考。这里是如何工作的代码如下所示:

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

我期待你的贴缺少一些括号,因为这将无法编译。也许你的意思是:'if(SvTYPE(SvRV(value))== SVt_PVAV)'? – LeoNerd

+0

代码更新,谢谢。 –

+0

@ikegami我更新了我的问题。问题,我没有看到关键'a'的标量值输出。 –

回答

3

难道我们总是从hv_iternextsv()返回的引用,有时它返回标?

它总是返回一个标量。哈希值只能是标量。这些标量可以是参考($h{x} = [];),但不一定是($h{y} = 123;)。

为什么我看不到关键a的标量值输出。

有没有办法,你可能可能回到你说的它做什么,看到你的哈希没有命名d关键。对于您提供的哈希值,你的代码输出以下:

key a has scalar value 
key c has hash value 

但它比什么都重要,你答对了巧合。 SvTYPE(SvRV(value))value不是参考?这是没有意义的!固定的代码如下:

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"}}); 

输出:

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

更新了我的答案。 – ikegami

+0

我再次调用该代码以获得散列,因此它会生成该输出。我添加了引用检查,它显示键“a”的值不是引用。所以我的第二个问题仍然有效。 –

+0

不要说谎。它被回答了,但你在一小时后改变了它。如果您有新问题,请在评论中或作为适当的问题提问。 //你可以使用'SvTYPE'来检查标量的类型,但是你为什么要这么做。如果你想要一个字符串,使用'SvPVutf8'。如果你想要一个整数,使用'SvIV'等。你不应该在乎它是如何存储的。 – ikegami