my @array= 0xffffffffffffffdf,0x2347,0x2360,0x2365,0xffffffffffffffcf,0x00,0x4a
我有一个1字节,2字节和8字节数据的数组。 数组中的2和8字节数据将随机出现
我想将2个字节的数组分成1个字节的每个字节,例如(0x2347
---> 0x23,0x47
)
我想将8字节的有符号数据截断为1字节,例如{0xffffffffffffffcf
---> 0xcf
)
my_code:
use strict;
use warnings;
my@array="0xffffffffffffffdf,0x2347,0x2360,0x2365,
0xffffffffffffffcf,0x00,0x4a";
my @split_array;
my @new_array;
foreach my $index (@array)
{
my @split_array;
if (length $index >4)
{
@split_array = map "0x$_", $index =~ /../g;
}
elsif (length $index>16)
{
@split_array = map "0x$_", $index =~ /../g;
}
else
{
@split_array = $index;
}
@new_array=join(", ", @split_array);
}
print "@new_array\n";
我的代码输出:
0x0x,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0x,0,0xx2,0x34,0x7 ,, 0x0x,0x23,0x60,0x,0,0xx2,0x36,0x5 ,, 0x0x ,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xcf,0x,0,0xx0,0x0,0x0x,0x4a 0x0x,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xcf
预期产出:
0xdf,0x23,0x47,0x23,0x60,0x23,0x65,0xcf,0x00,0x4a
请建议我解释一下步骤..?
答案 0 :(得分:2)
您希望-33(0xffffffffffffffdf
)成为df
(它的字节存储为带符号的8位整数)。
您希望9031(0x2347
)成为23 47
(它的字节存储为big-endian无符号16位整数)。
因此,除了值之外,您还需要提供应转换值的类型(例如Uint16
)。 您缺少这些必要的信息。
其他两个答案试图通过猜测类型来解决这个问题,将小于256的值转换为单个输出字节。但是,您的小组之前提供的data表明"0x02"
可能需要转换为0x00,0x02
0x02
。
因此,正如您的一位队友之前已经told,,您无法从您提供的信息中获得所需的结果。例如,要获得输出渴望,你需要
my @data = (
[ 'Sint8', '0xffffffffffffffdf' ],
[ 'Uint16', '0x2347' ],
[ 'Uint16', '0x2360' ],
[ 'Uint16', '0x2365' ],
[ 'Sint8', '0xffffffffffffffcf' ],
[ 'Sint8', '0x00' ],
[ 'Sint8', '0x4a' ],
);
完成后,您可以使用之前发布的solution。
use strict;
use warnings;
no warnings qw( portable );
use feature qw( say );
my %packers = (
Uint8 => sub { pack 'C*', @_ },
Sint8 => sub { pack 'c*', @_ },
Uint16 => sub { pack 'S>*', @_ },
Sint16 => sub { pack 's>*', @_ },
Uint32 => sub { pack 'L>*', @_ },
Sint32 => sub { pack 'l>*', @_ },
);
my $packed = '';
for (@data) {
my ($type, $hex) = @$_;
# Convert to number (and fix sign).
my $val = unpack 'q', pack 'q', hex $hex;
my $packer = $packers{$type}
or die("Unsupported type \"$type\"\n");
$packed .= $packer->($val);
}
say
join ',',
map { sprintf("0x%02x", $_) }
unpack 'C*',
$packed;
输出:(完全符合预期)
0xdf,0x23,0x47,0x23,0x60,0x23,0x65,0xcf,0x00,0x4a
答案 1 :(得分:1)
你的程序有很多错误
每次更改时,您应至少LazyDataModel
print
的值
以下是一些观察
在请求帮助之前,请至少整理并缩进代码。抛弃这样的东西并要求修复
您的$index
(除了有可怕名称 - @array
已经说过它是一个数组,因此@
部分毫无价值)只包含一个元素,这是一个82个字符的字符串,中间有换行符和空格
使用执行一次的array
循环将该字符串分配给变量for
(同样,一个可怕的名称 - 数组索引是从零开始的整数)
首先测试字符串的长度是否为> 4.此测试将始终首先成功,即使是超过16个字符的字符串也应该由第二个测试处理。请记住,你有一个字符串,长度为82个字符
请注意,即使您设法将$index
设置为$index
,也会将其字符串化为类似0xffffffffffffffdf
的内容,如果您只是将每对字符视为十六进制数字
答案 2 :(得分:0)
map {($_ & 0xffffffffffff0000) ? ($_ & 0xff) : (($_ & 0xff00) >> 8, ($_ & 0xff))} @array;
map是迭代数组的关键字。它允许产生更多的项目作为输出而不是输入。
为了识别2字节数据中的8字节数据,我使用了一个掩码。如果位设置在低16位之外,则表示它是8字节数据。
为了分割两个字节的数据,我也使用了掩码。
答案 3 :(得分:0)
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
my @input_hex = (0xffffffffffffffdf,0x2347,0x2360,0x2365,
0xffffffffffffffcf,0x00,0x4a);
my @output_hex;
for (@input_hex) {
if ($_ > 0xffff) {
push @output_hex, ($_ & 0xff);
} elsif ($_ > 0xff) {
push @output_hex, ($_ & 0xff00) >> 8, ($_ & 0xff);
} else {
push @output_hex, $_;
}
}
say join ',', map { sprintf '0x%02x', $_ } @output_hex;
在你解释你的问题时,我会尽可能多地努力解释我的答案 - 即没有。