Python驼峰转换问题:stdin输入中\r\n字符来源排查
问题:HackerRank驼峰字符串转换中\r\n字符异常问题
我在HackerRank上做Python驼峰字符串互转的练习,拆分驼峰字符串为小写空格分隔格式时遇到了问题:本地PyCharm运行一切正常,但平台上部分测试用例会出现莫名的\r\n字符。比如平台给出的测试用例是“S;V;iPad”(本身没有换行符),但代码debug打印显示words变量的值是'iPad\r\n',最终输出列表里也带着这个字符,想搞清楚这些\r\n是哪来的,怎么解决。
我的代码如下:
import sys import re ui = sys.stdin.readlines() def split_camel(words): split_list = re.split('(?=[A-Z])', words) print(f"{words=}") split_s = " ".join(split_list).lower().replace("(", "").replace(")", "") return split_s def combine_camel(kind, words): for i in str(words): if not i.isalnum(): words = words.replace(i, ' ') s = words.lower().split() s2 = s[0] + ''.join(i.capitalize() for i in s[1:]) if kind == "M": s2 = s2 + ("()") if kind =="C": first = s2[0].upper() s2 = first + s2[1:] return s2 def parse_input(ui): output = [] for line in ui: op, kind, words = line.split(';') if op == 'S': output.append(split_camel(words)) elif op == 'C': output.append(combine_camel(kind, words)) else: print("something wrong") return output print(parse_input(ui))
平台输入:
S;V;iPad C;M;mouse pad C;C;code swarm S;C;OrangeHighlighter
平台输出:
words='iPad\r\n' words='OrangeHighlighter' ['i pad\r\n', 'mousePad()', 'CodeSwarm', ' orange highlighter']
问题原因
sys.stdin.readlines()会把每行末尾的换行符(包括Windows风格的\r\n)完整读入。当你用line.split(';')拆分时,最后一个字段words会带上这些换行符,比如第一行处理后words就变成了'iPad\r\n'。本地PyCharm测试时可能用的是Unix风格换行符\n,或者输入没有多余的\r,所以没触发这个问题。
另外,split_camel函数里的正则拆分还会导致另一个问题:当字符串以大写字母开头时,re.split('(?=[A-Z])', words)会在开头生成一个空字符串,最终join后会出现前置空格,也就是平台输出里第四个结果的' orange highlighter'。
修复方案
- 移除换行符:处理每行前先去掉末尾的换行符,用
rstrip('\r\n')精准移除,避免误删其他字符:
def parse_input(ui): output = [] for line in ui: # 先移除行尾的换行符 line = line.rstrip('\r\n') op, kind, words = line.split(';') if op == 'S': output.append(split_camel(words)) elif op == 'C': output.append(combine_camel(kind, words)) else: print("something wrong") return output
- 过滤空字符串:修改
split_camel函数,拆分后过滤掉空元素,解决前置空格问题:
def split_camel(words): # 拆分后过滤空字符串,避免前置空格 split_list = [part for part in re.split('(?=[A-Z])', words) if part] print(f"{words=}") split_s = " ".join(split_list).lower().replace("(", "").replace(")", "") return split_s
修改后重新提交,就能解决这两个问题。
内容的提问来源于stack exchange,提问作者prosody
相关产品推荐
相关产品推荐

