首页 / 资讯中心 / 文章详情

PTA Python编程题第二章题解:输入输出、格式控制与常见坑位排查

PTA Python编程题第二章题解:输入输出、格式控制与常见坑位排查 ★ FEATURED ARTICLE
PTA-Python题库编程题 第二章(2.1~2.14)题解整理最近不少刚学Python的同学都卡在这一章的提交格式上。题本身不难逻辑最多的也就两三个分支但PTA这种在线判题系统有个特点结果对不一定能过格式差一点都不行。我刷完这14道题之后最大的感受是这一章其实是在用最基础的题目逼你把输入输出、类型转换、格式化这三件事彻底弄干净。这篇就把2.1到2.14按题型重新归类每道题给思路、给代码、给易错点最后附一份我刷题时踩过的坑和排查笔记拿去做参考大概率比你一道一道试错要快。这章适合刚学完变量和运算符的初学者也适合那些“在本地能跑、一提交就错”的同学。如果你已经能独立写出前三章的大部分题这篇就看最后的避坑清单就行。我会尽量用口语讲代码都是可以直接粘进PTA跑通的程度个别题号不同学校章节顺序可能有差异但核心考点和套路是一致的。1. 先把这章题目的“题感”建立起来读题、输入输出与判题规则1.1 这章到底在考什么第2章整体处于顺序结构阶段先不用慌循环和列表大部分题可以拆成三个动作从标准输入读数据做一次数学或字符串运算然后按题目给出的排版输出结果。很多同学栽跟头不是不会算是没搞清楚三个前提。第一input()读进来的东西永远是字符串哪怕你输入的是“123”它也是字符串123直接拿去加减乘除必然报错。第二一行里如果有多个数字input()默认把整行都读进来需要先按空格切分再逐个转类型。第三PTA评测时只会对比标准输出你多一个空格、少一个换行、大小写不一致都会被判成大错。所以写代码之前先花十秒钟确认输入有几行、每行几个数、输出要什么格式。这一章的另一个隐藏考点是对“精确输出”的耐心。比如保留两位小数、不足两位补零、右对齐、字符串原样输出这些要求看着细碎但后面的章节会反复出现。现在不养成习惯到列表和循环的题里再回头改格式化会特别别扭。1.2 提交前必须确定的四件事第一件事确认改完代码后用的是英文标点。PTA的判题机对中文引号、中文逗号非常敏感看起来差不多的符号编译直接挂掉。第二件事确认输入函数用对了。单个整数就n int(input())一行多个整数就a, b map(int, input().split())一句话概括就是“一次读行按空格切分批量转类型”。第三件事确认print的格式控制。需要小数位数的用f-string需要对齐的用:或:需要补零的用:02d。第四件事确认结尾换行。一般print默认带换行别画蛇添足多加空格就行。# 一行读入两个整数并计算加法 a, b map(int, input().split()) print(f{a} {b} {a b})这段代码虽然简单却包含了本章最常用的输入输出套路。split()不传参数时默认按连续的空白字符切分所以多个空格也不怕。map(int, ...)的作用是把切出来的每个字符串都转成整数结果可以直接解包给两个变量。这里尤其要注意变量数量必须和实际输入数量一致否则会报ValueError: not enough values to unpack。1.3 PTA判题信号分别对应什么问题PTA的反馈信息看着简单其实每一类都指向一类原因。我用一张表把它说明白排查时直接对着找。反馈信息含义最常见的实际原因Accepted完全正确无Wrong Answer输出与预期不符公式写错、格式多空格、边界情况没考虑Runtime Error运行时崩溃数组越界、除数为0、类型转换失败Presentation Error格式错误空格数不对、换行缺失、中文标点Compile Error编译失败Python语法错误、缩进错误、中英文符号混用Non Zero Exit Code非零退出程序异常结束常见于map数量不匹配提个醒Presentation Error在PTA早期版本里经常出现它和Wrong Answer的区别是计算结果对但排版有问题。有的同学喜欢在print里面手动拼空格拼多了或拼少了很容易触发这个反馈。我的习惯是优先用f-string或格式化方法让程序自己管对齐不手动数空格。2. 2.1~2.4从“会说话”到“会算数”四道必练的输出与运算题2.1 最典型的“输入计算并按指定格式输出”这一类的代表题目是输入两个整数输出它们的和、差、乘积或商同时要求保留某些文字前缀。看起来简单但失分点很集中。a, b map(int, input().split()) print(f{a} {b} {a b}) print(f{a} - {b} {a - b}) print(f{a} * {b} {a * b})可能你会说这有什么好讲的但我见过太多人写成print(a, , b, , ab)。这种写法在本地跑没问题问题在于逗号会自动转成空格输出的间距可能和题目要求完全不一致最终触发Wrong Answer。f-string把这些变量嵌进字符串里面就绕开了print多参数的空格问题。如果题目要求保留小数位数比如输出a / b并保留两位小数可以直接在{}里写格式说明a, b map(int, input().split()) print(f{a} / {b} {a / b:.2f})这行代码背后有个细节/在Python3里的结果一定是浮点数所以a / b的类型是float。格式化的时候:.2f表示保留两位小数这个语法在后面的每一道题都会用到建议现在记熟。2.2 华氏温度与摄氏温度的互转温度转换是第2章的经典题几乎每个版本都会出现。常见公式是C 5 * (F - 32) / 9也就是摄氏温度等于华氏度减32的差乘5再除以9。f float(input()) c 5 * (f - 32) / 9 print(f{c:.2f})先说一个很多人掉过的坑把公式写成5 / 9 * (f - 32)。在Python里这没问题因为会先算乘法除法但如果你写的是5 / 9 * (f - 32)当f是整数时也没问题可一旦换算成别的公式比如9 * c / 5 32就要小心整数的行为。Python3里/永远是浮点除法//才是整除所以这个坑不算太大真正要小心的是把5 * (f - 32) / 9误写成5 * f - 32 / 9那运算顺序就完全错了。这个题目还有个常见变形输入一个摄氏温度输出华氏温度保留两位小数。代码就是把公式反向写。c float(input()) f 9 * c / 5 32 print(f{f:.2f})浮点数这里还有一个隐藏问题float(input())在输入是整数32时能正常转成32.0但如果题目明确说输入是整数你也可以先int再转float。PTA测试点通常比较仁慈不会在这里设置小数溢出。2.3 计算圆的面积或周长用不用math.pi的差别在哪圆面积和圆周长也是这章的常客题目一般会让你输入半径r输出面积或周长保留若干位小数。有的版本允许你用3.14代替π有的版本要求精确到一定位数所以直接看题意。import math r float(input()) area math.pi * r * r circumference 2 * math.pi * r print(f{area:.2f}) print(f{circumference:.2f})如果题目没有明确要求π取值尽量用math.pi它会提供更高精度。你手动写3.14一旦遇到保留4位小数以上的情况后续位数全是错的。另一个常见错误是写r ** 2没问题但写r ^ 2就完全错了因为^在Python里是按位异或不是幂运算。这里也顺带说明import math的作用范围。import语句放在文件顶部之后的代码都能用math.pi、math.sqrt这些功能。如果在函数内部突然想用又没导入就会报NameError: name math is not defined。2.4 格式化输出里的“控位”题右对齐、补零、保留宽度2.4附近通常会有一些题目要求你输出特定宽度的数字比如“按5位宽度输出不足补零”或者“右对齐输出”。这些题考的就是f-string的格式语法。n int(input()) print(f{n:05d}) print(f{n:5d}):05d的意思是用0填充到5位比如输入42输出00042:5d的意思是右对齐到5位前面用空格补齐输出42。这两个看起来相似实际用途完全不同一个用于数字补零一个用于对齐排版。这类题还有一个变种输出多列数据要求每个数字占固定宽度且彼此之间有空格。我的建议是先构造格式化后的字符串再拼接减少出错概率。比如要输出a和b各占5列a, b map(int, input().split()) print(f{a:5d}{b:5d})注意中间不要手动加空格因为每个字段的宽度已经包含了空格对齐。这是PTA排版题最常见的丢分点你看着本地输出顺眼但评测机一比多态空格就炸了。3. 2.5~2.8字符、拆数、时间换算这轮的题开始“绕一下”3.1 逆序输出或多位数拆解从2.5开始题目不再是简单的“输入两个数算结果”开始要求你处理整数的每一位。最常见的是输入一个三位数输出它的百位、十位、个位或者直接输出逆序数。先上最简单的逆序法把输入当字符串处理。s input().strip() print(s[::-1])[::-1]是字符串切片逆序输入123会输出321。这种方式对付“逆序输出”的题很快但要注意题目是否对数值本身有要求。比如输入120字符串逆序得到021如果题目要的是整数21那你得用int再转一次。s input().strip() print(int(s[::-1]))int(021)的结果是21前导0也就自动去掉了。还有一种情况是题目要求严格按位输出比如“逆序后依次输出每一位”这时就不能用int转换而要保留字符串结果或者用取余拆数的思路。n int(input()) while n 0: print(n % 10, end) n // 10% 10取出个位// 10去掉个位循环输出就是逆序。这种方式对数字长度不固定的题目更通用。我一般先看题目是“按字符串处理友好”还是“按整数处理友好”再选方案不要只会其中一种。3.2 时间换算秒数转小时、分钟、秒时间换算题非常经典输入总秒数输出时:分:秒的格式而且经常要求分钟和秒用两位显示。total int(input()) hours total // 3600 minutes total % 3600 // 60 seconds total % 60 print(f{hours}:{minutes:02d}:{seconds:02d})这里重点解释两个运算符//是整除取商%是取余。total // 3600算出一共有多少小时total % 3600算出除掉整小时后还剩多少秒再整除60就得到分钟最后的total % 60就是秒。如果不理解这个逻辑后面处理更复杂的数值拆分会很吃力。f{minutes:02d}表示把整数minutes输出成至少两位不足两位前面补0所以5会变成05。这种写法在时间、日期、编号输出里极常见。有的题目要求秒和分保留两位小时不用补零这个规则要看清楚别统一套02d。还有一种变形是把输入分成小时和分钟让你计算总分钟数或反向换算逻辑就是乘法和除法的互换。不要死记公式理解“大单位化小单位要乘小单位化大单位要除”就够了。3.3 字符加密与大小写转换这章偶尔会有一道跟字符处理相关的题比如输入一个小写字母输出对应的大写字母或者输入一个字符输出它的ASCII码。这里引入的是ord()和chr()两个内置函数。ch input().strip() print(ord(ch)) num int(input()) print(chr(num))ord(a)得到97chr(97)得到a。这两个方法在字符转换题里是核心。大小写转换还有一种快捷方式ch input().strip() print(ch.upper()) print(ch.lower())但注意upper和lower都是生成新字符串不会改变原字符串内容。如果题目要求“判断是否为大写字母”可以用ch.isupper()返回布尔值。这类题本身不难真正的坑是input()读入的可能是换行符残留所以最好加一个.strip()把两侧空白去掉。之前我在本地测试怎么都对一提交就WA后来发现是循环读入时上一次的换行残留到了下一次输入里。3.4 统计某个字符在字符串中出现的次数和字符有关的统计题最直接的方式是count()方法。s input().strip() ch input().strip() print(s.count(ch))count()会计算子串在字符串里出现的次数写法上非常省事。有些人会手写循环去数也不是不行但在这章还没讲循环的情况下用内置方法反而更贴近题目本意。需要注意count()前面是原字符串后面参数是待查找的字符顺序别反了。4. 2.9~2.12浮点数、数学函数、带公式的分段题4.1 分段函数计算用if-elif把条件写清楚从2.9开始部分题目从表达式计算升级成分段函数。最常见的格式是当x满足某种条件时用某个公式否则用另一个公式。x float(input()) if x 0: y x ** 0.5 else: y (-x) ** 0.5 print(f{y:.2f})这只是一个示例实际题目会根据需要改公式。分段题的考点有三个。第一个是条件边界比如“大于等于0”和“大于0”的区别写错一个等号就整题错。第二个是浮点数输入如果是整数也不要紧float()可以兼容。第三个是公式本身要从题目里“抽”出来不能想当然。先读清分段条件再翻译成代码。有些分段题目还要求多重条件比如if x 0: result 0 elif x 10: result x * 2 else: result x * 3elif表示“否则如果再判断”程序会从上往下依次检查命中一个就不再往下走。这里有一种常见错法把elif写成else ifPython里没有else if这种写法编译直接报语法错误要注意。4.2 存款利息、复利计算这类带公式的题复利计算题几乎是每套题库的保留项目。题目通常给你本金、年利率和存期要求输出到期本息或利息保留两位小数。principal float(input()) rate float(input()) years int(input()) amount principal * (1 rate) ** years interest amount - principal print(f{interest:.2f})这里的关键是**幂运算符它比*优先级高。把(1 rate) ** years先算出来再乘本金这样才符合复利公式。不要写成principal * (1 rate) ** years被误解其实这行的优先级是右结合的先算(1rate) ** years再乘principal和我上面写的是一回事。如果你有疑惑可以多用一对括号提升可读性。这类题最大的坑是“年利率到底是百分数还是小数”。题目如果说“年利率为5%”那你处理时分两种输入是5代码里要写rate 5 / 100输入就是0.05则直接用。不确定的时候可以先在本地上打印amount看看数量级如果明显不合理大概率是百分数没转成小数。4.3 平方根和数学库的灵活使用有些题目要求开平方既可以用math.sqrt()也可以用x ** 0.5。在我实际使用中两者结果基本一致但math.sqrt语义更清晰遇到非负数的合法性也容易检查。import math x float(input()) print(f{math.sqrt(x):.2f})需要注意当x是负数时math.sqrt会抛出ValueError: math domain error程序直接崩溃。如果题目没说x一定非负要么加判断要么改用绝对值。有些同学为了避免导入math用x ** 0.5这样对负数不会报错但结果是复数输出格式可能会更麻烦。做题时以题目限定的输入范围为准不在范围外过度纠结。如果题目要判断一个整数是否是“完全平方数”可以用int(math.sqrt(x)) ** 2 x来校验。这个过程涉及浮点数误差极端大的整数偶尔会判断失误但PTA测试数据通常不会刁钻到那种程度。4.4 平均值、方差之类的基础统计题基础统计题在前几章偶尔会出现例如输入多个数求平均或方差。这里先看一道平均值a, b, c map(int, input().split()) avg (a b c) / 3 print(f{avg:.2f})如果题目的输入是“一行多个数用空格分隔”map(int, input().split())配合解包是最标准做法。但如果题目有四个、五个数写成a, b, c, d, e ...就很不优雅这时可以用列表nums list(map(int, input().split())) avg sum(nums) / len(nums) print(f{avg:.2f})虽然第二张node不一定讲列表但用这种内置函数组合会让代码更稳。“sum(nums)”求和“len(nums)”求个数避免手写多个变量。对于还没学到列表的同学也可以把list理解成一个装数据的容器直接整体算统计量比一个个变量方便。方差公式更复杂一点但思路是先求均值再求每个数与均值的差的平方的平均值。nums list(map(float, input().split())) mean sum(nums) / len(nums) variance sum((x - mean) ** 2 for x in nums) / len(nums) print(f{variance:.2f})这段用了生成器和循环对新手跳跃有点大。能看懂就参考看不懂就先把平均值的做法练熟。PTA这阶段更多是考平均数和总分方差出现频率较低。5. 2.13~2.14综合输出题与格式敏感题套路全在这里5.1 输出三角形、数字金字塔这类循环格式题有些版本的第2章会提前出现“输出金字塔”或“输出直角三角形”的题考的是多重循环和字符串重复。虽然题目可能在2.13才出现但核心逻辑要先讲清楚。n int(input()) for i in range(1, n 1): print( * (n - i) * * (2 * i - 1))解析这行代码外层循环控制行数i从1到n。每一行由两部分组成前半部分是空格后半部分是星号。第i行前面的空格数是n - i星号数是2 * i - 1。这是输出直角或等腰三角形最通用的规律。如果题目要求的是左对齐的直角三角形代码更简单n int(input()) for i in range(1, n 1): print(* * i)这里的难点不在写代码而在“别把题目要求的字符看错”。有的题用*有的题用#有的题要求输出数字本身比如第i行输出1 2 3 ...。只要记住“每行内容 该行需要的字符拼接”基本都能应付。数字金字塔的难度在于数字不是单一字符不能只用乘法。一种常见写法是n int(input()) for i in range(1, n 1): line .join(str(j) for j in range(1, i 1)) print( * (n - i) line) .join(...)把数字列表以空格连成字符串。这里你可能会觉得语法复杂但它确实更接近后续章节的循环题提前接触一下也好。如果读不懂就先用最笨的双层循环拼字符串结果一样只是代码长一点。5.2 多组重复输出格式题避免手写重复print另一些2.13~2.14范围内的题可能要求你输出很多行同格式的内容。比如输入一个数n输出n行“Hello”或者输出一个由指定字符组成的方阵。n int(input()) for _ in range(n): print(Hello)_在这里只是占位变量表示“我不关心循环到第几次”。新手往往想不到可以用循环来重复输出而是一个print一个print地写一旦n是变量就傻了。理清“循环体 一行输出”这个思路这类题就通了。还有一种题目要求交替输出不同字符比如奇数行用#偶数行用*。这时候可以用if i % 2 0判断奇偶再选字符。n int(input()) for i in range(1, n 1): if i % 2 1: print(# * i) else: print(* * i)我这里用的是“取模判断奇偶”也是本章和后续内容里反复复用的技巧。奇数i%2为1偶数i%2为0记下这个判断方法后面很多题目都用得上。5.3 “输入一个三位数分别输出百位、十位、个位”的两种解法压轴题或综合题里经常出现按位拆分的需求。比如输入123期望输出1 2 3或百位是1十位是2个位是3。解法至少有两种。第一种是字符串索引法s input().strip() print(s[0], s[1], s[2])简单直观但前提是输入保证是三位数且前导0不需要纠正。如果输入012它也会正常输出0 1 2而数字拆分会丢失前导零因为int(012)会变成12。第二种是整数拆法n int(input()) hundred n // 100 ten n % 100 // 10 one n % 10 print(hundred, ten, one)对于普通三位数这两种结果一样。区别在前导0和取值灵活度上。PTA这种题一般输入是普通三位数哪种方案都能过。但如果你未来要做多位数分离建议把取余和整除的思路吃透。n // 100去掉后两位n // 10 % 10或者n % 100 // 10取中间一位n % 10取最后一位随便选一套自己记住。6. 刷这章时我反复遇到的坑每题可能丢分的6个细节6.1 别只在样例数据上“肉眼验证”就算通过PTA几乎每个题都有隐藏测试点你在本地把样例跑出来不等于全对。比如题目说“输入非负整数”隐藏测试点可能包含0题目说“输入两个正整数a、b”隐藏测试点可能包含差距很大的数。拿到题先想清楚边界最大值、最小值、0、负值、小数点后很多位的数。在这些情况下你的代码是否还能输出正确格式最好把这些情况在本地快速测一遍。6.2 每行结尾的换行和行内空格一定要和样例完全一致我见过很多次同学代码输出内容是“1 2 3”但PTA期望是“1 2 3 ”或者反过来。最稳妥的验证方法是把输出结果逐字符比对不看数字本身。尤其注意print默认在结尾加一个换行这通常是符合评测要求的但如果题目要求同一行的多个数据之间用空格就不要用print多参数输出因为逗号会自动补空格。6.3 读入时用strip()去掉换行和多余空白循环读入字符串的场景中input().strip()是最安全的写法。字符串题尤其容易踩这个坑因为换行符是不可见字符你打印出来看到的是正常结果但程序判断时会多出一个\r或\n导致完全匹配失败。s input().strip()这一行代码在处理单个字符、单词、每行纯字符串时都非常推荐。如果是读入多个数字split()本身会处理两端空白所以input().split()已经足够不一定要再strip。6.4 map数量不匹配导致的Non Zero Exit Code最常见的运行时错误就是“输入了两个数代码用三个变量去接”。比如题目输入a b你却写了a, b, c map(int, input().split())立刻就会报错PTA显示为Non Zero Exit Code或Runtime Error。排查方法很简单数一下input返回的那一行里有几个数字再看赋值等号左边有几个变量。这一步看似低级但压力大时特别容易看错。如果遇到一行输入个数不固定的题不要用固定数量的变量去解包改用列表。try: nums list(map(int, input().split())) except: # 处理异常输入6.5 浮点数精度和保留小数round(2.675, 2)在Python里的结果不是2.68而是2.67因为2.675在二进制浮点数里其实是2.674999...。很多同学在这个问题上翻车明明数学上该进位但输出全错。所以涉及输出保留小数的题建议使用格式化而不是round。f{x:.2f}和print(%.2f % x)本质上都做的是十进制格式化比直接round更接近考题要求。差异虽然只在边缘情况体现但这种边缘情况正是PTA喜欢放的隐藏测试点。6.6 缩进和混合中英文标点Python对缩进极其敏感。同一个代码块里不能一会儿用空格一会儿用Tab否则会报IndentationError。更隐蔽的是复制讲义代码时常会带进来中文括号、中文引号、中文冒号这些在本地IDE可能被高亮出来但提交到PTA的纯文本环境就会编译失败。每次提交前检查一遍冒号、括号、引号是否都是英文半角状态能省掉很多无意义的重交。7. 常见问题速查表与独家避坑经验下面这张表是我做第2章时反复遇到的情况直接整理成速查格式出了问题对着找就行。症状排查方向解决提示显示Compile Error中英文符号、缩进统一英文标点检查缩进一致性显示Wrong Answer公式、边界、格式先逐字核对样例输出再测0和负数显示Presentation Error多余空格、换行缺失用f-string格式化不手动拼空格显示Non Zero Exit Code解包数量不匹配数清输入个数或改用list(map(...))输出和本地不一样换行符残留字符串输入加.strip()小数进位不对浮点数精度用格式化代替round答案超时死循环检查while退出条件这里再补充几个我自己的独家经验。第一把常用的输入模板背下来就是map(int, input().split())这种做题时直接写不要临时敲减少语法错误。第二不要一开始就在PTA的编辑框里写代码先在本地文本或IDE里写好跑通再粘贴提交。PTA在线编辑器没有语法高亮写长代码很容易漏看括号。第三每道题提交前先点“格式错误”自查也就是把输出区域的空格和换行明确列出来心里默念一遍。我在刷这章时最后悔的一点就是前几题一心想“快”结果一提交就错反而来回折腾。后来改成“先审题、再写框架、再填细节”效率高很多。还有些题目会要求输出空行或特定分隔符。比如“每组输出后跟一个空行”很多人会在最后多打印一个空行导致格式错误。处理方法是先把不要空行的情况跑通再按题意加空行加的时候用print()单独一行不要和内容混在一起。另外一点特别想提醒不要照搬网上的题解就交。PTA后台会查重或至少会做相似度分析更重要的是不同批次的测试数据可能不完全一样直接抄来的代码一旦运行环境或输入边界不一致照样会挂。我把题解写详细是为了让你理解套路不是让你复制粘贴交作业。最后再分享一个小技巧如果某道题怎么改都过不了可以故意提交一次带中文注释的版本看看反馈是否变成编译错误以此确认自己能正常通过输入输出。这种“提交测试法”虽然会多占一次提交次数但往往能快速排除环境层面的问题剩下就专心找逻辑错。这章做完了后面进入循环、列表、字符串处理时你会发现很多基础套路都是从这一章延伸出去的。把输入输出和格式化练稳比多刷十道题都值。
阅读完成 · 觉得有帮助?
咨询建站