页次: 1
定义以下函数,一次读取一个汉字(3个字节):
def get3char():
ch = ''
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
while True:
tmp = sys.stdin.read(1)
if tmp == '\x1b': # ESC
return '\x1b'
elif tmp == '\r': # RETURN
return '\r'
elif tmp.isalnum():
pass
else:
ch += tmp
if len(ch) == 3: break
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
问题是:输入一个4字节字符如 ? (\xf0\xa0\x9c\x8e) 时,最后一个字节 \x8e 会残留在缓冲区内。造成下次输入正常3字节汉字时乱码。
如何将其清理掉?
谢谢!
离线
你为什么要 if len(ch) == 3: break?
你换 Python 3 应该就好了。
离线
非常感谢回答。我的实际意图是制作一个中文打字练习/测速程序,使用 get3char() 一次输入一个汉字。
如果不加 if len(ch) == 3: break,输入完第一个中文字符后无法自动返回之,会一直读取。
根据个人肤浅的了解,使用 Python 3 应该在中文字符串处理时比较方便,对于这个具体问题有无助益?
谢谢!
目前的实际代码是这样的:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import sys
import tty
import time
import termios
from textwrap import wrap
def extract_char(txt, i):
return txt[i*3-3:i*3]
def get3char():
ch = ''
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
while True:
tmp = sys.stdin.read(1)
if tmp == '\x1b': # ESC
return '\x1b'
elif tmp == '\r': # RETURN
return '\r'
elif tmp.isalnum():
pass
else:
ch += tmp
if len(ch) >= 3:
break
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch[:3]
def do_drill(script):
global count, line_number
count += 1
if count%2 != 0 and count > 1:
raw_input("\nPress RETURN to continue")
sys.stdout.write("\033c")
sys.stdout.flush()
elif count%2 != 0:
sys.stdout.write("\033c")
sys.stdout.flush()
script = script.rstrip()
length_of_script = len(script)/3.
if not length_of_script.is_integer():
print "Script contains alphanumeric text."
line_number += 1
return 'passed'
else:
length_of_script = int(length_of_script)
print " "
print " "
print " ", script
sys.stdout.write(" ")
sys.stdout.flush()
typed = 0
mistyped = 0
for i in range(1, length_of_script+1):
char_typed = get3char()
if i == 1:
time_start = time.time()
if char_typed == '\x1b':
print "Aborted."
sys.exit()
elif char_typed == '\r':
break
elif char_typed != extract_char(script, i):
sys.stdout.write('\x1b[6;37;41m'+char_typed+'\x1b[0m')
sys.stdout.flush()
mistyped += 1
typed += 1
else:
sys.stdout.write(char_typed)
sys.stdout.flush()
typed += 1
time_stop = time.time()
elapsed_time = round(time_stop-time_start, 2)+0.01
speed = round(60*(typed-1)/elapsed_time, 2)
if speed < 0 or speed > 999:
speed = "N/A"
else:
speed = str(speed)+'cpm'
print ' '
print ' '
print ' Line: '+str(line_number)+', Elapsed: '+str(elapsed_time)+'s, Speed: '+speed
print ' Expected: '+str(length_of_script)+', Typed: '+str(typed)+', Mistyped: '+str(mistyped)
if mistyped == 0:
line_number += 1
return 'passed'
else:
return 'meh'
def main():
in_fname = sys.argv[1] if len(sys.argv) > 1 else 'mydrill'
chunk_size = int(sys.argv[2]) if len(sys.argv) > 2 else 35
f = open(in_fname)
txt = f.read()
f.close()
list_of_drill_script = wrap(txt, chunk_size*3)
global count, line_number
count = 0
line_number = 1
for each_line in list_of_drill_script:
while True:
status = do_drill(each_line)
if status == 'passed': break
if __name__ == "__main__":
main()
最近编辑记录 alexxey (2017-01-22 17:38:19)
离线
你试试 codecs.open 把流弄成 unicode 的吧。汉字并不都是三个字节的。
你要自己实现读取一个 (Unicode)字符的话,UTF-8 编码是很有规律的,你去维基百科看一下,然后自己写一个读取一个字符的函数吧。
Python 3 里的 str 实际上对应于 Python 2 里的 unicode 类型。它们用来处理字符比较方便。
最近编辑记录 依云 (2017-01-22 18:07:44)
离线
非常感谢指出正确方向,我会进一步学习。目前这个办法确实太简陋了。
实际上我是看到这位网友制作的“linux终端窗口下的中文打字练习”
http://blog.chinaunix.net/xmlrpc.php?r= … id=4025789
实际使用起来发现限制较多,个人又不会修改c代码,于是打算用python再实现一个类似的。
-----------------------
http://www.i18nguy.com/unicode/supplementary-test.html
离线
页次: 1