Модераторы: korob2001, ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> unpack, Узнать, сколько байтов было извлечено 
V
    Опции темы
Logo
Дата 24.9.2012, 21:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 694
Регистрация: 22.7.2008

Репутация: 3
Всего: 10



Как узнать, сколько байтов было извлечено функцией unpack? Что бы распаковать байтовую строку в цикле, смещая указатель.
PM MAIL   Вверх
arto
Дата 24.9.2012, 21:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1495
Регистрация: 31.10.2004

Репутация: 38
Всего: 40



а как вы её распаковываете?
PM MAIL ICQ   Вверх
Logo
Дата 24.9.2012, 22:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 694
Регистрация: 22.7.2008

Репутация: 3
Всего: 10



В данный момент - множествами unpack, отдельными на каждый элемент, вот так
Код

sub gs_game_info {
  my($rec) = @_;
  my %r;
  $r{date}          = unpack('L', $rec);
  $r{count_players} = unpack('C', substr($rec, 4, 1));
  $r{duration}      = unpack('S', substr($rec, 5, 2));
  #7+2
  $r{unknown}       = unpack('S', substr($rec, 7, 2));
  $r{len_map_name}  = unpack('C', substr($rec, 9, 1));
  $r{map_name}      = substr($rec, 10, $r{len_map_name});
  $r{len_game_name} = unpack('C', substr($rec, 10+$r{len_map_name}, 1));
  $r{game_name}     = substr($rec, 10+$r{len_map_name}+1, $r{len_game_name});
  my $p = 10 + $r{len_map_name} + 1 + $r{len_game_name}; # pointer
  for(my $n = 0; $n < $r{count_players}; $n++) {
    my %pl; # player
    $pl{rank}        = unpack('C', substr($rec, $p, 1));
    $pl{result}      = unpack('C', substr($rec, $p+1, 1)); # 0 - Victory! 1 - Defeat. 3 - ??? other - ?unknown?
    $pl{game_points} = unpack('L', substr($rec, $p+2, 4));
    $pl{theam_mask}  = unpack('C', substr($rec, $p+6, 1));
    $pl{color}       = unpack('C', substr($rec, $p+7, 1));
    $pl{nation}      = unpack('C', substr($rec, $p+8, 1));
    $pl{pid}         = unpack('L', substr($rec, $p+9, 4));
    $pl{len_nick}    = unpack('C', substr($rec, $p+13, 1));
    $pl{nick}        = substr($rec, $p+14, $pl{len_nick});

    $p += 14 + $pl{len_nick};
    $pl{max_game_points} = unpack('S', substr($rec, $p, 2));
    $pl{max_population}  = unpack('S', substr($rec, $p+2, 2));
    @{$pl{game_points_chart}} = unpack('C*', substr($rec, $p+4, 32));
    @{$pl{population_chart}}  = unpack('C*', substr($rec, $p+4+32, 32));
    $p += 4 + 32*2;
    push @{$r{players}}, \%pl;
  }
  $r{points_after_game} = unpack('S', substr($rec, $p, 2));
  $r{points_changes}    = unpack('c', substr($rec, $p+2, 1));

  return \%r;
}

Если знать, сколько байтов было извлечено, можно обойтись несколькими unpack с шаблонами.
PM MAIL   Вверх
arto
Дата 24.9.2012, 23:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1495
Регистрация: 31.10.2004

Репутация: 38
Всего: 40



А скомбинировать никак?
Опции формата имеют известную длину, можно вытащить длины полей.

my @ary = unplack "LCSSC", $rec;
@hash{@names} = unpack "LCSSCa$ary[4]Ca$ary[4]...", $rec

PM MAIL ICQ   Вверх
Logo
Дата 25.9.2012, 10:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 694
Регистрация: 22.7.2008

Репутация: 3
Всего: 10



Как это часто бывает, уже сам разобрался, надо поставить . в той позиции, в которой нужно узнать смещение относительно начала данных, спасибо. Теперь можно будет объединить.

Код

my @ary = unplack "LCSSC", $rec;
@hash{@names} = unpack "LCSSCa$ary[4]Ca$ary[4]...", $rec

Можно выбрать строки через C/a одним unpack.

Это сообщение отредактировал(а) Logo - 25.9.2012, 10:25
PM MAIL   Вверх
Logo
Дата 25.9.2012, 21:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 694
Регистрация: 22.7.2008

Репутация: 3
Всего: 10



Вот что вышло
Код

sub gs_game_info {
  my($rec) = @_;
  my %r;
  my $p; # pointer
  (@r{qw<date count_players duration unknown map_name game_name>}, $p) = unpack(
    "    L    C             S        S       C/a      C/a          .", $rec
  );
  for(my $n = 0; $n < $r{count_players}; $n++) {
    my %pl; # player
    
    # result => 0 - Victory! 1 - Defeat. 3 - ??? other - ?unknown?
    (@pl{qw<rank result game_points theam_mask color nation pid nick max_game_points max_population>}, $p) = unpack(
      "x$p  C    C      L           C          C     C      L   C/a  S               S                 .", $rec
    );
    (@{$pl{game_points_chart}}[0..31], $p) = unpack("x$p C32.", $rec);
    (@{$pl{game_points_chart}}[0..31], $p) = unpack("x$p C32.", $rec);

    push @{$r{players}}, \%pl;
  }
  @r{qw<points_after_game points_changes>} = unpack("x$p Sc", $rec);  
  return \%r;
}

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0919 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.