如何在 Perl 中反转无符号字节的位?

问题描述 投票:0回答:4

例如,数字 178 应转换为字母“M”。

178 是 10110010。

反转所有位应得到 01001101,即 77 或“M”字符。 我教过如何使用 Reverse 函数,但我不知道如何在 @array 上使用它。

use strict;
use warnings 'all';

    open(my $fh1, '<', 'sym.dat') or die $!;
    open(my $fh2, '<', 'sym2.txt') or die $!;
    open my $fh_out, '>', 'symout.txt' or die $!;

    until ( eof $fh1 or eof $fh2 ) {

        my @l1 = map hex, split '', <$fh1>;
        my @l2 = map hex, split '', <$fh2>;
        my $n = @l2 > @l1 ? @l2 : @l1;

        my @sum = map {
            no warnings 'uninitialized';
        $l1[$_] + $l2[$_];
    } 0 .. $n-1;
        @sum = map { split //, sprintf '%08X', $_ } @sum;
        print { $fh_out } "reverse @sum\n";
    }

我在这里计算十六进制值的总和,但问题是一样的,我想反转字节值。

perl
4个回答
2
投票

只需将数组传递给函数即可在数组上调用

reverse()
。然而,像所有 Perl 函数一样,您不能将函数调用放在字符串中。所以而不是

print { $fh_out } "reverse @sum\n";

你想要:

print { $fh_out } reverse(@sum), "\n";

此处需要使用

@sum
周围的括号,以防止换行符包含在
reverse
的参数中。


1
投票

这会反转位:

>perl -E"say pack 'C', ~178 & 0xFF"
M

这会反转位:

>perl -E"say pack 'B8', unpack 'b8', pack 'C', 178"
M

这会反转位:

>perl -E"say pack 'b8', sprintf '%08b', 178"
M

0
投票

我能想到的最短的反转是

~pack "C", 178
(eta:但是你的标题和文本对于你是否想要翻转位或反转它们来说非常混乱,你的位模式对于两者都有相同的结果,但是这个一般情况下并不相同)。在后一种情况下,可以这样做
pack "B8", scalar reverse unpack "B8", pack "C", 178
,只是不要忘记添加评论;-)。


0
投票

这可能不是最有效的方式,但是:

sub reverse_bits {
    oct '0b' . join '', reverse split '', sprintf '%08b', shift;
}
printf '0b%08b', reverse_bits oct '0b10110010';  # 0b01001101
© www.soinside.com 2019 - 2024. All rights reserved.