【问题标题】:Trying to print ASCII characters 128 to 160, why does it stop at 157?尝试打印 128 到 160 的 ASCII 字符,为什么会在 157 处停止?
【发布时间】:2022-01-19 01:13:04
【问题描述】:

我是 Python 新手,正在学习编码/编码、unicode、ascii 等。 我想根据它们的代码并使用 chr() 函数打印 ASCII 字符。

def table_ascii():
    "procédure imprimant une table des caractères ascii avec leur valeurs"
    i = 127
    while i < 258:
        print(f"{i} -> {chr(i)}")
        i += 1

table_ascii()

不幸的是,结果是错误的。它在代码 157 处停止:

127 ->  
128 ->  
129 ->  
130 ->  
131 ->  
132 ->  

133 ->  

134 ->  
135 ->  
136 ->  
137 ->      
138 ->  
139 ->  
140 ->  
142 ->  
143 ->  
144 ->  
146 ->  
147 ->  
148 ->  
149 ->  
150 ->  
151 ->  
152 ->  
154 ->  
        155 ->  

157 ->

我知道这些代码返回空白,但为什么它们会停止该过程?

设置:

  • Python 3.8.10(默认,2021 年 9 月 28 日,16:10:42) [GCC 9.3.0] 在 Linux 上
  • 使用 VIM - Vi IMproved 8.1

当我在 Visual Studio Code 中运行此代码时,脚本会通过 256 生成输出。但在我的控制台 (Linux Mate) 中,它会阻塞。这对我来说很难理解......

【问题讨论】:

  • 你的任务的前提是有缺陷的。 ASCII 仅定义整数值 0-127 的字符。 没有对应于整数 128-160 的 ASCII 字符。将 128-160 解释为字符严格要求使用 ASCII 以外的编码(尽管可能是 ASCII 的超集)。
  • chr 返回 Unicode 字符串,并且由于历史原因,没有为代码点 127 到 159 定义(可打印)字符。
  • 运行此代码会为我生成 257 的输出
  • 另外说明,由于您正在学习,因此您可以在一个范围内循环,而不是手动增加 i,例如 for i in range(0, 128)
  • 我在我的机器(Ubuntu 20.4,python 3.9)上确认了相同的效果:在 ipython 中运行代码或作为显示在终端中的脚本,它在 157 处停止。

标签: python ascii


【解决方案1】:

首先,ASCII 最多只能达到 127 (0x7F)。 chr() 实际上返回 Unicode 字符。

我认为问题在于,当打印 U+9D (157) 操作系统命令 (OSC) 时,您的终端会启动一个控制字符串并等待像 U+9C 这样的字符串终止符 字符串终止符,U+1B 转义后跟U+5C反斜杠,或U+7 BEL。由于以后不会打印这些序列,因此终端停止显示输出。有关详细信息,请参阅 Wikipedia 上的 ANSI escape code § Fe Escape sequencesC1 control codes

Unicode 字符 U+80 (128) 到 U+9F (159) 是控制字符,这意味着它们通常不可打印,因此您一开始就无法获得合理的输出。

【讨论】:

  • 太棒了!我将打印行更改为 print(f"{i} -&gt; {chr(i)}{chr(0x9c)}") 以始终确保它被终止并且可以正常工作
【解决方案2】:

正如 cmets 中提到的,128 到 160 之间的字符在某种程度上是无人区。它们在 Unicode 规范中没有定义,但它们可能对各种显示具有特殊含义。这就是为什么 Unicode 不涉及它们的原因 - 太多的变量在起作用。

诸如 Linux xterm 之类的终端接受控制代码来执行诸如以彩色显示文本之类的操作。看着Xterm Control Sequences我们看到了

Privacy Message (PM is 0x9e)

这是 158 个十进制数,它是 xterms 8 位控制字符之一。这将启动一条“私人消息”,该消息一直持续到看到定义的字符串终止符为止。 xterm 没有实现“私人消息”,它从您的输出中看起来它只是忽略了作为该消息的一部分的剩余输出。

这是一个 VT100 类型的东西。一些终端可能会执行一些动作。其他人可能有一个映射到该八位字节的字符。你不会找到任何一致的实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-26
    • 1970-01-01
    • 1970-01-01
    • 2011-02-05
    • 1970-01-01
    • 2021-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多