Saladino has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks, I have a struct wich contains
struct mystruct{ int id[10]; char text[40]; unsigned short int len;
And I'm trying to unpack it in a single line, something like this:
my(@ids,$text,$length) = unpack("N10C40n",$buff) ;
But everything is going to the first array, i've tried templates as "N10 C40 n" and "(N10)(C40)(n)"
So, either this can't be done or I'm not using the proper template string.
Any hint?

Thanks

Replies are listed 'Best First'.
Re: unpack() to several variables
by Fletch (Bishop) on Jul 22, 2009 at 13:03 UTC

    The assignment to the array will eat up all the values so no you can't do it in just one go (if the array comes before the individual scalars; if the scalars came first it would have just worked as you have it now); you could however capture everything in @ids then use splice or pop to remove $text and $length afterwards.

    Update: D'oh, yeah it'll work fine with a slice of fixed length as psini proffers below. Ned moar caffeine apparently . . .

    Update 2: Well, will work with a more appropriate unpack string ("c40" returns a list of 40 characters-as-numbers, not a string of 40 characters); "a", "A", or "Z" is probably more what the OP's looking for.

    use strict; use warnings; use YAML::Syck qw( Dump ); my $src = pack( "N10 a5 n", 0..9, "abcde", 99 ); my( @a, $b, $c ); (@a[0..9],$b,$c) = unpack( "N10 a5 n", $src ); print Dump( { a => \@a, b => $b, c => $c } ), "\n"; exit 0; __END__ --- a:   - 0   - 1   - 2   - 3   - 4   - 5   - 6   - 7   - 8   - 9 b: abcde c: 99

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

      Maybe using an array slice? As in (untested):

      my(@ids,$text,$length); (@ids[0..9],$text,$length) = unpack("N10C40n",$buff) ;

      Rule One: "Do not act incautiously when confronting a little bald wrinkly smiling man."

        Please, note that with those lines of code instead of geting the C40 to $text I get C1 to $text and C2 to $length
Re: unpack() to several variables
by jbt (Chaplain) on Jul 22, 2009 at 13:01 UTC
    'N' is an 32 bit long. Try 'i' and 'c': i10c40i
Re: unpack() to several variables
by Marshall (Canon) on Jul 22, 2009 at 13:20 UTC
    Its been awhile since I did this pack/unpack stuff in Perl. But, Yes! This can be done in Perl! Intel is little endian, VAX order! Not Motorola big endian order. Read the section on "Pack" very carefully in Larry's book, page 757-762 very carefully.
      As pointed out by Fletch in the reply before yours, the OPs error had nothing to do with pack or its arguments, but with the fact that having an array on the LHS of a list arguments will gobble up all the remaining arguments.
      I'm reading big endian integers
        here is my "go at it". Its been years since I looked at pack or unpack..But I would suggest when solving a problem like this, make a binary file first that is known to be big "endian" and then work from there. My code for the unpack looks a bit strange. Fletch has some great code above. Anyway make a binary file that you know to be right, then work from there. Packing is easier than unpacking different size data things. My binary "binout" file assumes 32 bit big endian and typical character byte packing for that architecture.
        #!/usr/bin/perl -w use strict; my @x = (0x1230,0x1231,0x1232,0x1233,0x1234, 0x1235,0x1236,0x1237,0x1238,0x1239); my @c = qw (a b c d e f g h i j); open (BIN, '>', "binout") || die " unable to open binout"; binmode (BIN) || die "unable to set binmode"; print BIN pack('N'x10,@x); print BIN pack('a'x10,@c); close(BIN); open (BIN, '<', "binout") || die "CAN'T OPEN BINOUT ?!"; while(my $buff = <BIN>) { my (@tokens)= unpack ('N10C10', $buff); foreach my $digit (@tokens[0..9]) { printf "%x \n",$digit; } foreach my $char (@tokens[10..19]) { printf "%c\n", $char; } } __END__ binout is: (hex) 0000 1230 0000 1231 0000 1232 0000 1233 0000 1234 0000 1235 0000 1236 0000 1237 0000 1239 0000 1239 6162 6364 6566 6768 696a output: 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 a b c d e f g h i j