Schrift
[thread]7114[/thread]

kompliziertes unpack



<< >> 3 Einträge, 1 Seite
Damokles
 2005-07-07 01:54
#56062 #56062
User since
2005-06-28
7 Artikel
BenutzerIn
[default_avatar]
Ich habe da mal eine Frage.
Wie Ihr unten sehen könnte habe ich viele unpack(substr) aufrufe. Kann man das irgendwie in einem großen unpack realisieren? Ich weiß das man Sachen mit (A C1 V)* zusammenfassen kann, aber wie realisiere ich das mit dem neuen Objekt und den entsprechenden Zuweisungen?

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
for (my $i = $args->{RAW_MSG_SIZE} % 106; $i < $args->{RAW_MSG_SIZE}; $i += 106) {
#exp display bugfix - chobit andy 20030129
$num = unpack("C1", substr($args->{RAW_MSG}, $i + 104, 1));
$chars[$num] = new Actor::You;
$chars[$num]{'exp'} = unpack("V1", substr($args->{RAW_MSG}, $i + 4, 4));
$chars[$num]{'zenny'} = unpack("V1", substr($args->{RAW_MSG}, $i + 8, 4));
$chars[$num]{'exp_job'} = unpack("V1", substr($args->{RAW_MSG}, $i + 12, 4));
$chars[$num]{'lv_job'} = unpack("C1", substr($args->{RAW_MSG}, $i + 16, 1));
$chars[$num]{'hp'} = unpack("v1", substr($args->{RAW_MSG}, $i + 42, 2));
$chars[$num]{'hp_max'} = unpack("v1", substr($args->{RAW_MSG}, $i + 44, 2));
$chars[$num]{'sp'} = unpack("v1", substr($args->{RAW_MSG}, $i + 46, 2));
$chars[$num]{'sp_max'} = unpack("v1", substr($args->{RAW_MSG}, $i + 48, 2));
$chars[$num]{'jobID'} = unpack("C1", substr($args->{RAW_MSG}, $i + 52, 1));
$chars[$num]{'ID'} = substr($args->{RAW_MSG}, $i, 4);
$chars[$num]{'lv'} = unpack("C1", substr($args->{RAW_MSG}, $i + 58, 1));
$chars[$num]{'hair_color'} = unpack("C1", substr($args->{RAW_MSG}, $i + 70, 1));
($chars[$num]{'name'}) = substr($args->{RAW_MSG}, $i + 74, 24) =~ /([\s\S]*?)\000/;
$chars[$num]{'str'} = unpack("C1", substr($args->{RAW_MSG}, $i + 98, 1));
$chars[$num]{'agi'} = unpack("C1", substr($args->{RAW_MSG}, $i + 99, 1));
$chars[$num]{'vit'} = unpack("C1", substr($args->{RAW_MSG}, $i + 100, 1));
$chars[$num]{'int'} = unpack("C1", substr($args->{RAW_MSG}, $i + 101, 1));
$chars[$num]{'dex'} = unpack("C1", substr($args->{RAW_MSG}, $i + 102, 1));
$chars[$num]{'luk'} = unpack("C1", substr($args->{RAW_MSG}, $i + 103, 1));
$chars[$num]{'sex'} = $accountSex2;
}
coax
 2005-07-07 08:50
#56063 #56063
User since
2003-08-11
457 Artikel
BenutzerIn
[default_avatar]
Die vielen substrs kannst du durch unpack ersetzen, dadurch fallen dann auch all die anderen unpacks weg.
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/usr/bin/perl

 use strict;
 use warnings;

 use vars qw(@chars);

 # Beispieldatensatz
 my $msg = '1111' . '2222' . '3333' . '4444' . 'A' . '_' x 25 .
           '55' . '66' . '77' . '88' . '_' x 2 .
           'B' .  '_' x 5 . 'C' . '_' x 11 .
           'D' . '_' x 3 . 'E' x 24 .
           'F' . 'G' . 'H' . 'I' . 'J' . 'K' . 'L' . '_';

 print("Ein Datensatz: $msg\n\n");

 # den gleichen Datensatz noch 2mal anghaengen
 $msg .= $msg x 2;

 # --- Begin interessanter Teil

 # String in Datensaetze splitten
 my(@records) = $msg =~ /(\w{106})/g;

 foreach my $record ( @records ) {
     my(%fields, $num);
     (@fields{qw(ID exp zenny exp_job lv_job hp hp_max sp sp_max
                 jobID lv hair_color name str agi vit int dex luk )}, $num)
          = unpack("V V V V C x25 v v v v x2 C x5 C x11 C x3 Z24 C C C C C C C", $record );

     $chars[$num] = \%fields;
 }

 # --- Ende interessanter Teil

 # Datensatz mit Index 76 ausgeben
 foreach my $key ( keys %{ $chars[76] } ) {
     printf("%s\t%s\n", $key, $chars[76]->{$key} );
 }


Code: (dl )
unpack("V V V V C x25 v v v v x2 C x5 C x11 C x3 A24 C C C C C C C", $record );

Wie du siehst sind die Einsen hinter V und C ueberfluessig jedes Zeichen steht schon fuer 'einmal'. Die Angabe x25 steht fuer 25 Nullbytes die dann in der Ergebnisliste auch nicht auftauchen, so kannst du leicht eine bestimmte Anzahl Zeichen ueberspringen.

Grusz Christian.

edit: Der alte $forumbeitrag =~ s/\_\_.+?\_\_//sg;-Bug :angry:\n\n

<!--EDIT|coax|1120712667-->
,,Das perlt aber heute wieder...'' -- Dittsche
Damokles
 2005-07-07 13:48
#56064 #56064
User since
2005-06-28
7 Artikel
BenutzerIn
[default_avatar]
Erst mal danke für die Antwort.
Könnte man das noch in einen einzigen unpack Aufruf packen, oder wäre das zu umständlich.
Kann man Perl dazu bringen mit hier mit 2dimensionalen Arrays zu arbeiten. Was ich meine er füllt das Array auf wie oben angegeben und wenn es voll ist fängt er von vorne an. Hoffentlich war das verständlich.
Code: (dl )
1
2
my $x = int (length($msg) / 106);
unpack("x2 (V V V V C x25 v v v v x2 C x5 C x11 C x3 Z24 C C C C C C C)$x", $msg )
<< >> 3 Einträge, 1 Seite



View all threads created 2005-07-07 01:54.