Последовательности байтов в Perl

У меня есть массив, и каждый элемент массива представляет собой массив из двух чисел, значения которых находятся в диапазоне 16 бит. Для каждого элемента в массиве мне нужно поместить эти 2 числа в 32-битное целое число, а затем сохранить его в таблице в базе данных MySQL в столбце типа varbinary.

Я думаю, мне нужно использовать pack с шаблоном S!, чтобы создать одно 32-битное целое число, содержащее 2 других числа в старших/младших 16 битах.
Я думаю, что мне нужно использовать pack с шаблоном I! для создания окончательного значения, которое будет сохранено в базе данных.
Но я не уверен, как я могу сделать это с pack, и я не очень понимаю пример в doc о том, как сформировать петлю.

my( $ip, $cs,
    $flags,$fl,$fh,
    $ax,$al,$ah, $bx,$bl,$bh, $cx,$cl,$ch, $dx,$dl,$dh, 
    $si, $di, $bp, $ds, $es ) =
unpack( 'v2' . ('vXXCC' x 5) . 'v5', $frame );
 

Может ли кто-нибудь помочь с тем, как я могу использовать pack для реализации этого? Или pack не подходит для обоих случаев?

Например, для создания одного 32-битного числа следующий фрагмент:

my $number1 = 120;
my $number2 = 3090;
my $word = pack( 'S!*S!*', $number1, $number2 );
print "$word \n";  

принты: x

Я ожидал, что он напечатает 1 число (32-битное целое число). Что я делаю неправильно/не понимаю здесь?

Обновление после комментария @ikegami:

  1. 32-битное целое число
  2. $number1 — старшие биты
  3. Большой порядок байтов

Обновление 2 после комментариев @ikegami. Я пробовал следующее:

my @array = (
 [120, 3090],
 [34, 2018],
 [47, 4005],
 [98, 2345],
 [111, 1]
);

my @packed;
foreach ( @array ) {
    my @elem = $_;
    print $elem[0][0]. " - ". $elem[0][1]. "\n";
    my $id = $elem[0][0];
    my $num = $elem[0][1];
    my $word = pack( 'S>2', $id, $num);
    push @packed, $word;
    say sprintf "%v02X", $word;
}

my $packed_output = pack('I*', @packed); // line 63
say sprintf "%v02X", $packed_output;

Это не удается со следующей печатью:

00.78.0C.12
120 - 3090
00.78.0C.12
34 - 2018
00.22.07.E2
47 - 4005
00.2F.0F.A5
98 - 2345
00.62.09.29
111 - 1
00.6F.00.01
Argument "\0x\f^R" isn't numeric in pack at line 63.
Argument "\0"^G?" isn't numeric in pack at  line 63.
Argument "\0/^O?" isn't numeric in pack at  line 63.
Argument "\0b^I)" isn't numeric in pack at  line 63.
Argument "\0o\0^A" isn't numeric in pack at line 63.
00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00
S! неправильно. Вам нужны ровно два 16-битных целых числа, а не два unsigned short (которые имеют размер не менее 16 бит, но могут быть и больше)
ikegami 20.11.2022 20:18

Два * неверны. S!*S!* это то же самое, что просто S!*, чего достаточно,

ikegami 20.11.2022 20:19

Re «Я ожидал, что он напечатает 1 число», нет, он выдает строку байтов. Но это на самом деле то, что вы хотите.

ikegami 20.11.2022 20:20

В этом вопросе отсутствует много информации. 1) Это 32-битное целое число со знаком или без знака? 2) Является ли $number1 или $number2 старшими битами? 3) Какой порядок следования байтов следует использовать (собственный, прямой или прямой)?

ikegami 20.11.2022 20:21

@ikegami: 1) 32-битное целое число без знака 2) $number1 - это самые значащие биты 3) прямой порядок байтов

Jim 20.11.2022 21:10

@ikegami: как unsigned short может быть больше 16 бит?

Jim 20.11.2022 21:12

C только гарантирует, что unsigned short будет как минимум -32767..32767

ikegami 21.11.2022 04:12
Шаблоны Angular PrimeNg
Шаблоны Angular PrimeNg
Как привнести проверку типов в наши шаблоны Angular, использующие компоненты библиотеки PrimeNg, и настроить их отображение с помощью встроенной...
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Если вы веб-разработчик (или хотите им стать), то вы наверняка гик и вам нравятся "Звездные войны". А как бы вы хотели, чтобы фоном для вашего...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Начала с розового дизайна
Начала с розового дизайна
Pink Design - это система дизайна Appwrite с открытым исходным кодом для создания последовательных и многократно используемых пользовательских...
Шлюз в PHP
Шлюз в PHP
API-шлюз (AG) - это сервер, который действует как единая точка входа для набора микросервисов.
14 Задание: Типы данных и структуры данных Python для DevOps
14 Задание: Типы данных и структуры данных Python для DevOps
проверить тип данных используемой переменной, мы можем просто написать: your_variable=100
2
7
91
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Закрывать.

Двойной * не имеет смысла. S!*S!* должно быть S!*, S!S! или S!2.

S! неправильно. Это относится к unsigned int, который имеет длину не менее 16 бит, но может варьироваться. Вы хотите именно 16-бит, так что должно быть S.

Вы также не указали порядок байтов. Поскольку вам нужен порядок байтов с большим концом, вам действительно нужен S> (или n).

my $packed = pack( "S>2", $number1, $number2 );  # "\x00\x78\x0C\x12"

say sprintf "%v02X", $packed;  # 00.78.0C.12

Как видите, получается строка из четырех байтов, а не число. Но это то, что вы хотите. VARBINARY используется для хранения последовательности байтов. При распаковке строки байтов с помощью L> получается 32-битное число.

Это вызывает альтернативу. Вы также можете вычислить 32-битное число и упаковать его.

my $packed = pack( "L>", $number1 << 16 | $number2 );  # "\x00\x78\x0C\x12"

say sprintf "%v02X", $packed;  # 00.78.0C.12

Ссылка: Форматы упаковки и распаковки номеров

Комментарии не для расширенного обсуждения; этот разговор был перемещен в чат.

sideshowbarker 23.11.2022 13:04

Другие вопросы по теме