Perl 设置/重置字符串上的第 8 位

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

给定一个字符串,我想要

  • A
    的所有字符设置为
    I
    的第 8 位(
    0x41
    ~
    0x49
    0xC1
    ~
    0xC9
    )。
  • 将所有第 8 位打开的字符重置为关闭。

喜欢,

$s='@ABCDEFGHIJKLMNOPQRS';
$s1= join "", map { $_ |= 0x80 if /A-I/ } split //, $s;
$s2= join "", map { $_ &= ~0x80 } split //, $s1;

我认为我上面的代码很接近,但它并没有完全工作。
请帮忙。

string perl bit-manipulation
1个回答
0
投票

您的代码有一些问题。

首先,传递给

map
的函数必须返回所需的值。您的代码将
$_
设置为所需的值(这很好,但没有必要),但是
$s1
的代码没有返回结果,因此最终得到一个空字符串。 (您的
$s2
代码确实返回了结果,因此在这方面没有问题,尽管写得有点奇怪。)

其次,

/A-I/
不是正确的正则表达式。你本来想写
/[A-I]/

第三,当 Perl 在字符串和数字之间进行转换时(例如,因为您使用字符串和数字调用了按位运算符),它是通过将字符串解析为数字或以 10 为基数格式化数字来实现的。例如,

'3' | 12
相当于
3 | 12
,即
15
,然后根据需要转换为
'15'
。那不是你想要的;相反,您对字符串中字符的 ASCII/Unicode/字节值感兴趣。对于此类转换,您需要使用
ord
(字符→数字)和
chr
(数字→字符)。但你不能写
chr(~0x80)
,因为
~0x80
0xFFFFFFFFFFFFFF7F
(假设是64位系统),这不是一个有效的字符代码。相反,您需要编写
chr(0x7F)
"\x7F"
,或者在按位运算之后应用
chr
,例如: chr(ord($_) & ~0x80)

所以,把它们放在一起,你可以写成这样:

$s = '@ABCDEFGHIJKLMNOPQRS'; $s1 = join "", map { $_ | (/[A-I]/ ? "\x80" : "") } split //, $s; $s2 = join "", map { $_ & "\x7F" } split //, $s1;
或者这个:

$s = '@ABCDEFGHIJKLMNOPQRS'; $s1 = join "", map { $_ = chr((ord $_) | 0x80) if /[A-I]/; $_ } split //, $s; $s2 = join "", map { chr(ord($_) & ~0x80) } split //, $s1;
或任何其他沿着这些思路的排列。

© www.soinside.com 2019 - 2024. All rights reserved.