1、编程需求
阿萌要开发一个长度单位换算器,帮助学生掌握长度单位的换算。

长度单位换算要求
程序要求学生输入一个带单位的长度数值,程序输出换算后其它单位的长度数值。支持的长度单位有:米、分米、厘米、毫米。
例如学生输入1分米,程序输出如下:
1分米 = 0.1米
1分米 = 10厘米
1分米 = 100毫米
2、分割子串
根据编程需求,程序需要识别出学生输入的单位和数值,并进行单位换算。
例如学生输入“3分米”,程序需要分割出数值3和分米,数值3是长度,分米是单位。

input函数返回的是字符串,实际就是对字符串的分割。程序需要编写一个cut函数来分割学生输入的字符串。
函数的功能是传入一个字符串,返回一个列表,该列表有两个元素,第一个元素是识别出的数值,第二个元素是识别出的单位。如果识别失败,返回空列表。
数值和单位分割算法
遍历字符串的所有字符,在遍历过程中,做如下处理:
如果字符是数字字符,且后续是连续数字字符,将该数字字符序列作为整数存入列表,作为列表的第一个元素,将数字字符之后的字符序列作为列表的第二个元素。
程序简化起见,算法假设学生按照程序要求输入了正确的数据,没有对学生的输入错误进行处理。
cut函数流程图如下:


cut函数代码如下:
# 定义函数cut def cut(instr): # 创建一个空列表 list = [] # 创建一个空字符串num # 用于存储数值 num = "" # 创建一个空字符串unit # 用于存储单位 unit = "" # 遍历instr for ch in instr: # 如果ch是字符,将ch添加到num if ch.isdigit(): num += ch # 否则将ch添加到num else: unit += ch # 添加num和unit到列表 list.append(int(num)) list.append(unit) # 返回list return list
代码解读
函数的功能是将学生输入的内容分割成两个子串,一个子串是数值,一个子串是单位,将分割出来的两个子串添加到list列表,函数返回list列表。
函数使用for……in……循环结构来遍历传入的字符串instr,循环变量ch是instr的一个字符。在第一轮循环时,ch是instr的第一个字符,在第二轮循环时,ch是instr的第二个字符,以此类推,直至instr遍历完成。
在for循环体中,判断ch是否是数字,如果是数字添加到num字符串中,如果不是数字添加到unit字符串。
str遍历完成后,将num转换为整数后添加到list列表,unit也添加到list列表。
3、认识序列对象
字符串也可以使用for……in……循环来遍历字符串中的所有字符,字符串和列表、元组一样都属于序列对象,序列对象都有索引,通过索引可以访问序列对象的元素,序列对象都可以使用for……in……循环来遍历序列对象中的全部元素。
序列是按照一定的顺序将元素排成一列,元素的数据类型没有限制,可以是任意类型的数据,如数字类型、字符串、布尔型、结构化数据(如列表)等。
对象是指一个事务,这个事务有属性和行为,事务的属性和行为被封装到一起。例如人也可以是一个对象,人有年龄、性别、体重等属性,也有跑步、吃饭、骑自行车等行为。

Python的列表、元组、字典、字符串等都是对象,它们不仅是一种数据结构,而且也封装了对该数据结构的属性和行为,对象中的行为也被称为方法,方法类似于函数,用于完成对象自身的部分功能。
例如在列表中添加元素的append()方法,完成列表对象的元素添加功能。列表、元组、字典、字符串这些对象还有很多方法,在以后的学习和编程过程中会逐渐用到。
4、程序数据结构的设计
在编写程序的过程中,程序数据结构的好坏,直接影响到程序的质量和代码的优化。
程序数据结构是指程序用来存储和组织数据的方式,好的数据结构可以提高程序的质量,能够简化代码,提高代码的运行效率。
在本编程案例中,编程需求是学生输入一个带单位的长度,程序输出换算成其它单位的长度。支持的长度单位有:米、分米、厘米、毫米。
程序需要存储单位间的进率,要存储长度单位米与分米、厘米、毫米间的进率,也要存储分米与米、厘米、毫米间的进率等,同理还要存储厘米、毫米与其它单位间的进率。
程序从学生的输入中获取了数值和单位后,需要获取该单位和其它单位间的进率,并将数值乘以进率进行单位换算,最后将换算结果输出到Shell窗口。
程序如何根据已有的单位来获取和其它单位间的进率?用什么样的数据结构实现?这是我们要重点考虑的。
可以考虑用字典数据结构来存储单位与其它单位间的进率。

在上面的数据结构中,单位“米”是字典的key,字典的value是一个字典,该字典存储了单位“米”与其它长度单位的进率。
当学生输入的单位是“米”时,可以通过key“米”获取字典的value,value也是一个字典,字典存储了“米”与其它单位的进率,遍历字典即可将“米”换算成其它单位。
例如:
学生输入12米,调用cut函数将12米分割为数值12和“米”,用“米”作为key获取字典的value,value也是字典,程序遍历value。
在遍历value的过程中,获取字典每个元素的key和value,key是单位,value是米换算为该单位的进率,用数值12乘以value,就可以将12米换算为与该单位相关的长度。
程序的数据结构如下:

编写convert函数,该函数传入长度的数值和单位,应用dict字典数据,将传入的长度单位换算为其它长度单位。
convert函数流程图如下:

函数首先创建一个空的列表,用于存储换算后的单位和数值,然后函数会判断传入的key是否在dict字典中,如果不在字典中直接返回空的list。
如果key在字典中,从字典中取出key的value并赋值给subdict,value也是一个字典,该字典存储了key表示的单位与其它单位的换算进率。
遍历subdict字典,在遍历字典的过程中完成单位换算。遍历完成,函数返回list列表。

在单位换算处理过程中,subdict字典元素的key是单位,进率是value。unit(单位)是key,通过key获取该value(单位的进率)。然后计算num(函数传入的参数,为长度数值)与value的乘积,最后以“单位:数值”方式添加到list列表。
convert函数代码如下:
def convert(num,key): # 创建空列表 list = [] # 判断key是否在dict if key in dict: # 获取key对应的字典 subdict = dict[key] # 遍历subdict for unit in subdict: value = subdict[unit] # 计算单位换算后的数值 newnum = num * value # 以“1分米=10厘米”类似方式添加到list list.append(str(num)+ key + "=" + str(newnum) + unit) return list
代码解读
函数传入的参数为num和key,num是整数类型,表示长度的数值(例如12),key是字符串类型,表示长度的单位(例如米)。
函数会把转换后的长度数值与单位,添加到list列表,并返回列表。
例如当函数传入的参数num为12,key为米时,转换后的列表内容:
['12米=120分米', '12米=1200厘米', '12米=12000毫米']
函数执行步骤如下:
(1)函数首先创建一个空列表list,然后判断传入的参数key是否在dict字典中,如果不在直接返回空列表;
(2)从dict字典中获取key对应的子字典,并赋值给subdict;
(3)遍历subdict字典,获取对应的key和value,此时key为要换算的单位,value为该单位的换算进率;
(4)计算单位换算后的数值;
(5)以“1分米=10厘米”类似方式添加到list。
5、 程序流程图

这是程序的主流程图,前面已经给出了cut函数和convert函数的流程图。
程序首先建立字典数据,然后输出提示信息,并等待学生的输入,如果学生输入的是quit,程序结束。
如果学生输入的不是quit,调用cut函数分割学生的输入,然后再调用convert函数进行单位换算,最后输出换算结果。程序流程再次回到输出提示信息步骤,等待学生的输入。
简化起见,流程图没有处理学生的输入错误。
6、程序代码及解读
程序代码如下:
'''
程序文件:main.py
功能描述:长度单位换算程序
代码编写时间:2020/04/18
作者:郎宏林
'''
# 定义字典数据
dict = {"米":{"分米":10,"厘米":100,"毫米":1000},
"分米":{"米":0.1,"厘米":10,"毫米":100},
"厘米":{"米":0.01,"分米":0.1,"毫米":10},
"毫米":{"米":0.001,"分米":0.01,"厘米":0.1}}
# 定义cut函数
def cut(instr):
# 创建一个空列表
list = []
# 创建一个空字符串num
# 用于存储数值
num = ""
# 创建一个空字符串unit
# 用于存储单位
unit = ""
# 遍历instr
for ch in instr:
# 如果ch是字符,将ch添加到num
if ch.isdigit():
num += ch
# 否则将ch添加到num
else:
unit += ch
# 添加num和unit到列表
list.append(int(num))
list.append(unit)
# 返回list
return list
# 定义convert函数
def convert(num,key):
# 创建空列表
list = []
# 判断key是否在dict
if key in dict:
# 获取key对应的字典
subdict = dict[key]
# 遍历subdict
for unit in subdict:
value = subdict[unit]
# 计算单位换算后的数值
newnum = num * value
# 以“1分米=10厘米”类似方式添加到list
list.append(str(num)+ key + "=" + str(newnum) + unit)
return list
# 程序入口
if __name__ == '__main__':
while(True):
# 输出提示信息
print("-------欢迎使用长度换算器-----\n")
print("请输入带单位的长度,例如:12分米、3米等\n")
print("换算器支持米、分米、厘米、毫米\n")
print("输入quit退出程序\n")
# 获取学生的输入
temp = input("请输入:")
# 判断学生输入的是否是quit
if temp == "quit":
break;
# 调用cut函数分隔字符串,函数返回列表
str_list = cut(temp)
# 调用convert函数进行单位换算
unit_list = convert(str_list[0],str_list[1])
# 输出unit_list
for item in unit_list:
print(item)代码解读
程序首先建立字典数据,并分别定义了cut函数和convert函数。然后进入while循环,在循环体内输出提示信息,并等待学生的输入。
学生输入后,程序先判断学生输入的是否是“quit”,如果是“quit”,则跳出循环,程序退出。
如果学生输入的不是quit,调用cut函数分隔字符串,然后再调用convert函数进行单位换算,最后遍历并输出convert函数返回的列表。
代码简化起见,程序并没有对学生的输入错误进行处理,感兴趣的同学,可以在源代码基础上添加对学生输入错误的处理代码。
