当前位置:   article > 正文

python数据结构实验设计(单链表):通讯录管理_python数据结构课程设计

python数据结构课程设计


摘要

课程设计结合本学期所学的数据结构和以前学习的python程序语言和c语言知识,数组、函数、结构体、指针、链表、文件读取操作等等,设计开发一个简单的通讯录管理程序。设计开发这个系统需要用到链表、文件读取操作、结构体、函数、指针、等C语言知识。本课程设计将会实现的功能包括:读取计算机文件里的通讯录联系人信息(姓名、号码、分组),并生成以名字为排序依据的单链表、统计联系人个数、对联系人信息进行准确查找和模糊查找、新增和删除联系人以及将两个通讯录合并。本着简单、易用的设计原则,设计出一款通讯录管理的程序。  


一、课程设计目的及内容

目的:用 python设计一个具有单向链表结构的通讯录管理程序,用于查询和修改

等便捷化操作通讯录信息文件。 

内容:

定义一个包含手机联系人信息(姓名,电话,分组)的链表,使其具有如下功能:

        (1) 从计算机已保存的文件读入联系人信息,并用直接插入排序法从无到有建立以姓名为排序 依据的单链表

        (2) 统计联系人个数;

         (3) 根据联系人姓名或电话进行查找,成功返回联系人记录;

         (4) 实现通过姓名的部分字眼进行查询时,显示包含该字眼的所有联系人记录;

         (5) 对于一个从键盘数据的新增联系人,能插入到已排好序的链表中;

        (6) 删除指定姓名或电话的联系人记录。 

创新功能:

实现两个手机通讯录链表的合并,合并之后仍然以名字为关键字排序。相同姓名、相同电话号码的记录删除其中一个,相同姓名、不同电话号码的记录通过输出询问进行电话号码合并或分别保存。

 

二、算法及设计过程分析

1.总流程

 

2.主界面

每个功能对应一个模块,模块引用读取文件后生成的单链表信息,其中修改后的链表也会写入文件 


3.文件处理与生成单链表

         (1)使用.csv文件的优点:每一行都是一个数据元素作为节点,而每个数据项都存放在一个单元格里(如右图所示),从而对其进行读取就非常简单了。在python中,对csv文件的读取会每行以列表的默认形式输出,而列表只需要输入下标即可输出每行每列的信息,从而输入到链表时每个结点里面的数据也是一个保存着联系人信息的列表,然后对链表的结点处理也能按照列表方式进行,非常方便。

        (2)由于在python中,中文字符串的比较经常会出错,比如:

>>> "啊">"吧"

True

        很明显,”啊”在中文里的拼音应该小于”吧”,而且如果比较的两个字符串里的中文长度不一样比较结果也千变万化。所以需要进行对中文转拼音后再进行比较,可以完全解决这个问题。所以编写了以下代码进行转换拼音比较(需要第三方库):

  1. #中文字符串比较问题
  2. from pypinyin import pinyin,Style
  3. from itertools import chain
  4. def toPinyin(s):
  5. return ' '.join(chain.from_iterable(pinyin(s, style=Style.TONE3)))

结果输出也非常有效,也可以看出,中文被转换成了拼音形式,能正确进行中文比较了。

>>> print(toPinyin("啊")>toPinyin("吧"))

False

>>> print(toPinyin("数据结构"))

shu4 ju4 jie2 gou4

4.查看所有联系人信息

 

这个很简单,直接打印链表即可。

但是存在两个问题:

一是链表直接打印只会返回一串形如 <address_book.Linklist.LinkedList object at 0x0000028984E5F130> 的十六进制的地址,所以打印需要将链表遍历一遍所有结点,因此重写链表的repr或str函数,该函数就是在类里面遍历一遍所有内容,然后返回一个对象的string,就可以直接打印链表了。

二是由于链表的数据元素以列表形式存放,肯定每个数据项的长度不一,因此输出后对齐就非常重要了。而python里面可以用ljust()或rjust()进行左或右对齐。

5.查看人数

直接调用链表函数ListLength()就可以了查看链表长度(即总人数)了。

而查看分组人数就需要先筛选出所有分组,然后再统计每个分组的人数,用两个循环就完成了。

6.查找联系人(以姓名或号码为依据)

 

 

7.对姓名或号码输入关键字进行模糊查找

 

 8.添加联系人

9.删除联系人 

输入信息后,遍历链表。若在链表中查找到该数据项则删除,否则提示无该联系人。

修改源通讯录文件:遍历文件的每一行的相关数据项(名字和号码),搜索到即删除该行信息。

10.合并两个通讯录

         输入两个文件路径后生成两个链表,若出现相同的联系人信息则合并,相同的名字不同的电话号码则分别输出两个信息后询问是合并号码还是分别保存

三、实验结果分析与总结

1.实验结果

        程序设计的运行结果比较理想,但是也有许多不足。比如排版尚未完全对齐,原版本在合并链表时发现相同的信息没有显示出来,左图。所以答辩结束后及时进行了修改,右图。

 2.总结

        通过完成这个通讯录管理的程序,很大程度上进一步了解了有关链表和结构体课程理论知识,这也是单纯的课堂上学不到的。“实践即是检验真理的唯一标准”,只有通过自己动手,才能更加了解理论知识,也才能更好地去一步步熟悉运用。

        做程序不仅仅是敲代码这么简单。当然,扎实的编程基础是最基本的,但是更需要的是注意力的集中和清晰地逻辑思维能力,这样在设计算法的时候才不会那么容易被自己写的东西绕晕,最好是在本子上写出或脑海里形成一个脉络框架然后一步步完成。最后再细心调试,修改bug,优化程序编译界面,添加必要注释,这一点也非常重要,因为有时候数据太多导致面板太乱,自己也会忘了数据内容(在做排序比较时改bug改到凌晨三点,最后发现居然是少打了个半括号...)。

        其次,团队合作能力也非常重要,总有擅长和不擅长的,所以在队伍里主动承担自己擅长的部分,遇到自己不熟悉的小组内一起解决,这样能大大提高工作效率。

四、完整代码

文件夹下:__init__.py为空文件,方便导入同目录下的模块包, .csv文件需要自己新建并以右图格式存放信息,首行为标注信息,第一列姓名,第二列号码,第三列分组

 

 

1.单链表模块(LinkList.py)

  1. #此模块为单链表以及各个函数的定义模块
  2. class LNode:
  3. """链表结点,名称为LNode"""
  4. def __init__(self, elem: int or str, next=None):
  5. self.elem = elem #结点数据域
  6. self.next = next #结点指针域
  7. class LinkedList:
  8. """链表"""
  9. def __init__(self):
  10. #链表初始化
  11. self.head = None #头结点指针域为空
  12. def ListEmpty(self):
  13. """判断是否为空链表,头节点为None则是空"""
  14. return self.head is None
  15. def ListLength(self):
  16. """求链表的长度"""
  17. p = self.head
  18. count = 0
  19. while p:
  20. count += 1
  21. p = p.next
  22. return count
  23. def ListClear(self):
  24. """清空链表"""
  25. self._head = None
  26. def LocateElem(self, value: int or str):
  27. # 根据值查找节点,函数返回结点
  28. p = self.head
  29. while p and p.elem != value:
  30. p = p.next
  31. if p==None:
  32. return None
  33. else:
  34. return p
  35. def LocateElem_first(self, value: int or str):
  36. # 根据值查找节点第一个元素项,函数返回是否查找到
  37. p = self.head
  38. while p and p.elem[0] != value:
  39. p = p.next
  40. if p==None:
  41. return False
  42. else:
  43. return True
  44. def GetElem(self, position: int or str):
  45. # 根据索引位置查找节点,需要挨个遍历,返回数据域的值
  46. p = self.head
  47. index = 0
  48. while p and index != position:
  49. p = p.next
  50. index += 1
  51. if p==None:
  52. return None
  53. else:
  54. print(p.elem)
  55. return p.elem
  56. ##########################################################
  57. #前插法
  58. def insert_node_to_head(self, node): #创建新节点插入表头,因之后函数需要用到插入新节点,所以单独创建函数
  59. if node:
  60. node.next = self.head
  61. self.head = node
  62. def insert_value_to_head(self, value: int or str): #将数据赋予表头结点数据域
  63. node = LNode(value)
  64. self.insert_node_to_head(node)
  65. ##########################################################
  66. def insert_elem_to_last(self, elem):
  67. #尾插法
  68. node = LNode(elem)
  69. p = self.head
  70. if not p:
  71. self.head = node
  72. else:
  73. while p.next:
  74. p = p.next
  75. p.next = node
  76. ##########################################################
  77. def insert_node_after(self, node, new_node):
  78. #插在指定元素后
  79. if not node or not new_node:
  80. return
  81. new_node.next = node.next
  82. node.next = new_node
  83. def insert_value_after(self, old_node, new_value):
  84. new_node = LNode(new_value)
  85. self.insert_node_after(old_node, new_node)
  86. #########################################################
  87. def insert_node_before(self, node, new_node):
  88. #插在指定元素前
  89. if not self.head or not node or not new_node:
  90. return
  91. if node == self.head:
  92. self.insert_node_to_head(new_node)
  93. return
  94. p = self.head
  95. while p and p.next != node:
  96. p = p.next
  97. if not p:
  98. return
  99. new_node.next = node
  100. p.next = new_node
  101. def insert_value_before(self, value: int or str, node):
  102. new_node = LNode(value)
  103. self.insert_node_before(node, new_node)
  104. #########################################################
  105. def delete_by_node(self, node):
  106. # 删除某个节点
  107. if not self.head or not node:
  108. return
  109. # 不是最后一个节点,可以直接删除, 删除的复杂度为O(1)
  110. if node.next:
  111. node.elem = node.next.elem
  112. node.next = node.next.next
  113. else:
  114. p = self.head
  115. while p and p.next != node:
  116. p = p.next
  117. if not p:
  118. return
  119. p.next = node.next
  120. def delete_by_value(self, value: int or str):
  121. # 删除某个值对应的节点
  122. if not self.head or not value:
  123. return
  124. fake_head = LNode(-1)
  125. fake_head.next = self.head
  126. prev, current = fake_head, self.head
  127. while current:
  128. if current.elem != value:
  129. prev.next = current
  130. prev = prev.next
  131. current = current.next
  132. if prev.next: # current.item == value
  133. prev.next = prev.next.next
  134. self.head = fake_head.next
  135. ######################################################
  136. def InsertSort(self):
  137. if not self.head:
  138. return
  139. fakehead=LNode(None) #创建哨兵
  140. p=self.head
  141. while p:
  142. t=p.next #下一结点
  143. q=fakehead #将每一次遍历的结点赋予哨兵
  144. #找到p结点插入的位置
  145. while q.next and q.next.elem<=p.elem:
  146. q=q.next
  147. p.next=q.next
  148. q.next=p
  149. p=t
  150. ######################################################
  151. def __repr__(self): #由于直接将链表结果打印出来会变成一串十六进制码,所以需要进行重写函数
  152. # 打印链表,重写repr或者str函数
  153. a = []
  154. p = self.head
  155. while p:
  156. a.append(p.elem)
  157. p = p.next
  158. return "\t\n".join(map(str, a))

2.主代码

  1. import os
  2. import csv
  3. from pypinyin import pinyin,Style
  4. from itertools import chain
  5. import re
  6. from Linklist import * #同目录下找到LinkList.py文件,例如LinkList.py 在文件夹address_book下,
  7. #则修改为from address_book.LinkList import *(需要在目录下新建一个__init__.py的空文件)
  8. #或者将LinkList.py文件复制到环境包目录下,或者将所有代码放在同一个代码文件里不使用import
  9. import pandas
  10. #中文字符串比较
  11. def toPinyin(s):
  12. return ' '.join(chain.from_iterable(pinyin(s, style=Style.TONE3)))
  13. #判断字符串是否为中文
  14. def is_CN (mail_text: str):
  15. tmp_text = ''.join(mail_text.split())
  16. count = 0
  17. for s in tmp_text.encode('utf-8').decode('utf-8'):
  18. if u'\u4e00' <= s <= u'\u9fff':
  19. count += 1
  20. if float(count / (tmp_text.__len__())) > 0.1:
  21. return True
  22. else:
  23. return False
  24. class LinkList:
  25. #链表初始化读入文件信息,并排序
  26. def __init__(self):
  27. self.l=LinkedList()
  28. global path #文件路径
  29. while 1:
  30. # path = input(r"请输入通讯录文件路径,例如C:\book.csv:""\n")
  31. path=r"info.csv" #csv文件空行不能大于1,否则新增联系人会报错或每次多一个空行
  32. if not os.path.exists(path):
  33. print("->文件不存在,请重新选择文件\n")
  34. f=open(path,'r',encoding='utf-8')
  35. read=csv.reader(f)
  36. for i,lines in enumerate(read):
  37. if i>=1 and lines:
  38. empty=0
  39. break
  40. if not os.path.getsize(path):
  41. f.close()
  42. print("->文件为空,已为您增加表头注释信息,稍后请增加新联系人")
  43. first = ['姓名(names)', '电话号码(tel_number)', '分组(group)']
  44. f=open(path,'a',newline='')
  45. writer=csv.writer(f)
  46. writer.writerow(first)
  47. f.close()
  48. empty=1
  49. continue
  50. else:
  51. if next(read):
  52. empty = 0
  53. break
  54. if not next(read):
  55. print("联系人为空,请重新选择文件或手动添加联系人")
  56. empty=1
  57. break
  58. if empty==0:
  59. f=open(path,'r',encoding='utf-8') #以读取方式打开文件
  60. reader=csv.reader(f)
  61. next(reader) #第一行为注释信息,从第二行开始读取
  62. sort_info=[] #获取排列信息
  63. for lines in reader:
  64. sort_info.append(lines[0])
  65. f.close()
  66. sort_info=sorted(sort_info,key=toPinyin) #若有中文通过拼音进行排序
  67. for i in range(len(sort_info)): #将按照姓名排序好的信息依次插入单链表
  68. f = open(path, 'r',encoding='utf-8')
  69. reader = csv.reader(f)
  70. next(reader)
  71. for lines in reader:
  72. if sort_info[i]==lines[0]:
  73. self.l.insert_elem_to_last(lines)
  74. f.close()
  75. # 功能1,显示以名字为排序的单链表表示的通讯录
  76. def fun1(self):
  77. if self.l.ListLength()>0:
  78. print("-"*87)
  79. print("->信息按姓名进行从小到大排序,姓名信息的优先序列分别为:数字、大写字母开头英文字母、中文(小写英文开头)")
  80. print("-" * 87)
  81. #打印信息对齐
  82. s=["姓名(name)","电话(tel_number)","分组(group)"]
  83. maxname=len(s[0])
  84. maxnum=len(s[1])
  85. maxgroup=len(s[2])
  86. p=self.l.head
  87. while p:
  88. if len(p.elem[0])>maxname:
  89. maxname=len(p.elem[0])
  90. if len(p.elem[1])>maxnum:
  91. maxnum=len(p.elem[1])
  92. if len(p.elem[2])>maxgroup:
  93. maxgroup=len(p.elem[2])
  94. p=p.next
  95. maxlen=max(maxnum, maxgroup, maxname)
  96. print(s[0].ljust(maxlen, " "), s[1].ljust(maxlen, " "), s[2].ljust(maxlen, " "))
  97. p=self.l.head
  98. while p:
  99. if is_CN(p.elem[0]): #中文对齐英文比较困难,放弃了,就这样吧
  100. print(p.elem[0].ljust(maxlen-1, " "),
  101. p.elem[1].ljust(maxlen, " "), p.elem[2].ljust(maxlen, " "))
  102. else:
  103. print(p.elem[0].ljust(maxlen, " "),
  104. p.elem[1].ljust(maxlen, " "), p.elem[2].ljust(maxlen, " "))
  105. p=p.next
  106. else:
  107. print("->通讯录为空")
  108. #功能2,获取通讯录人数
  109. def fun2(self):
  110. print("->通讯录总人数:", self.l.ListLength())
  111. p=self.l.head
  112. if p!=None: #输出每个分组人数
  113. group=[p.elem[2]]
  114. while p:
  115. if not p.elem[2] in group:
  116. group.append(p.elem[2])
  117. p=p.next
  118. num=[]
  119. for i in range(len(group)):
  120. sum=0
  121. p = self.l.head
  122. while p:
  123. if p.elem[2]==group[i]:
  124. sum+=1
  125. p=p.next
  126. num.append(sum)
  127. max=len(group[0])
  128. for i in range(len(group)):
  129. if len(group[i])>max:
  130. max=len(group[i])
  131. print("每组人数分别是:")
  132. for i in range(len(group)):
  133. print(group[i].ljust(max," "),num[i])
  134. else:
  135. print("暂无分组信息")
  136. #功能3,根据姓名或号码查找联系人信息
  137. def fun3(self):
  138. while 1:
  139. print("\n")
  140. p=self.l.head
  141. if p==None:
  142. print("->通讯录为空,请新增联系人后再查找")
  143. break
  144. info=input("->输入想要查找的联系人姓名或电话号码,输入exit可退出: ")
  145. if info=='exit':
  146. os.system("cls")
  147. break
  148. flag=0
  149. while p:
  150. if p.elem[0]==info or p.elem[1]==info:
  151. print(p.elem,"\n")
  152. flag=1
  153. break
  154. else:
  155. p=p.next
  156. if p==None and flag==0:
  157. print("\n->查找失败,请重新输入,或输入exit退出。\n")
  158. break
  159. #功能4模糊查找
  160. def fun4(self):
  161. while 1:
  162. if self.l.head==None:
  163. print("通讯录为空,请新增联系人")
  164. break
  165. print("->请选择:\n"
  166. "1.模糊查找姓名\n"
  167. "2.模糊查找电话号码\n")
  168. choice=input("->请输入功能选择序号,输入exit退出模糊查找: " )
  169. if choice=='1':
  170. info=input("->请输入要查找的信息: ")
  171. p=self.l.head
  172. flag=0
  173. while p:
  174. if re.findall(info,p.elem[0]):
  175. print(p.elem)
  176. print()
  177. flag=1
  178. p=p.next
  179. if p==None and flag==0:
  180. print("-=>无您所查找的信息")
  181. print("-"*50)
  182. elif choice=='2':
  183. info=input("->请输入要查找的信息: ")
  184. p=self.l.head
  185. flag=0
  186. while p:
  187. if re.findall(info,p.elem[1]):
  188. print(p.elem)
  189. print()
  190. flag=1
  191. p=p.next
  192. if p==None and flag==0:
  193. print("->无您所查找的信息")
  194. print("-"*50)
  195. elif choice=='exit':
  196. break
  197. else:
  198. print("->输入有误")
  199. print("-" * 50)
  200. #功能5新增联系人
  201. def fun5(self):
  202. p=self.l.head
  203. if p==None: #通讯录为空时不显示分组信息
  204. print("当前无联系人信息,请新增联系人")
  205. newname=input("->请输入新联系人名字: ")
  206. newnumber=input("->请输入新联系人号码: ")
  207. newgroup = input("->请输入新联系人加入的分组: ")
  208. print("\n")
  209. newinfo = [newname, newnumber, newgroup]
  210. f = open(path, 'a',encoding="utf-8",newline='')
  211. writer = csv.writer(f)
  212. writer.writerow(newinfo) # 将新信息写入文件
  213. f.close()
  214. p.elem=newinfo
  215. print("->已经增加新联系人:\n姓名:{},电话号码:{},分组:{}".format(newname, newnumber, newgroup))
  216. print(self.l)
  217. else: #通讯录不为空时显示分组信息
  218. newname=input("->请输入新联系人名字: ")
  219. newnumber=input("->请输入新联系人号码: ")
  220. group=[self.l.head.elem[2]]
  221. p=self.l.head
  222. while p:
  223. if not p.elem[2] in group:
  224. group.append(p.elem[2])
  225. p=p.next
  226. print(group)
  227. newgroup=input("->请输入新联系人加入的分组,目前所有分组如上(若无该分组则自动创建分组): ")
  228. newinfo=[newname,newnumber,newgroup]
  229. f=open(path,'a',encoding='utf-8',newline='')
  230. writer=csv.writer(f)
  231. writer.writerow(newinfo) #将新信息写入文件
  232. f.close()
  233. p = self.l.head
  234. while p:
  235. if p.next==None:
  236. self.l.insert_elem_to_last(newinfo)
  237. break
  238. elif toPinyin(p.elem[0]) < toPinyin(newinfo[0]) and\
  239. toPinyin(p.next.elem[0]) > toPinyin(newinfo[0]):
  240. self.l.insert_value_after(p,newinfo)
  241. break
  242. elif toPinyin(p.elem[0])>toPinyin(newinfo[0]):
  243. self.l.insert_value_to_head(newinfo)
  244. break
  245. else:
  246. p=p.next
  247. print("->已经增加新联系人:\n姓名:{},电话号码:{},分组:{}".format(newname,newnumber,newgroup))
  248. #6,通过姓名或号码删除联系人
  249. def fun6(self):
  250. delete=input("->请输入想要删除的联系人姓名或号码: ")
  251. p=self.l.head
  252. while p:
  253. if p.elem[0]==delete or p.elem[1]==delete:
  254. self.l.delete_by_node(p)
  255. print("->已删除")
  256. break
  257. if p.next==None:
  258. print("->联系人信息不存在!")
  259. break
  260. p=p.next
  261. #查找删除信息在文件中的位置
  262. f=open(path,'r',encoding='utf-8')
  263. i=1
  264. reader=csv.reader(f)
  265. next(reader)
  266. for lines in reader:
  267. if lines[0]==delete or lines[1]==delete:
  268. break
  269. i+=1
  270. f.close()
  271. #在文件中删除该信息行
  272. data = pandas.read_csv(path,encoding='utf-8')
  273. data.drop(data.index[i-1], inplace=True)
  274. data.to_csv(path, index=0)
  275. #合并两个通讯录,先合并,后排序
  276. def connnect():
  277. while 1:
  278. path1=input(r"->请输入通讯录1文件路径: ")
  279. path2=input(r"->请输入通讯录2文件路径: ")
  280. if os.path.exists(path1) and os.path.exists(path2):
  281. break
  282. else:
  283. print("->其中有文件不存在,请重新输入:")
  284. #通讯录1
  285. l1=LinkedList()
  286. f1=open(path1,'r',encoding='utf-8')
  287. reader1=csv.reader(f1)
  288. next(reader1)
  289. for lines in reader1: #将文件信息写入链表,暂不排序
  290. l1.insert_elem_to_last(lines)
  291. #通讯录2
  292. l2=LinkedList()
  293. f2=open(path2,'r',encoding='utf-8')
  294. reader2=csv.reader(f2)
  295. next(reader2)
  296. for lines in reader2:
  297. l2.insert_elem_to_last(lines)
  298. #两个链表合并后将新链表的内容写入新文件保存
  299. l3=LinkedList()
  300. p1=l1.head
  301. while p1:
  302. p2=l2.head
  303. while p2:
  304. if p1.elem[0]==p2.elem[0] and p1.elem[1]==p2.elem[1]: #两个通讯录相同的
  305. l3.insert_elem_to_last(p1.elem)
  306. p2=p2.next
  307. continue
  308. if p1.elem[0]==p2.elem[0] and p1.elem[1]!=p2.elem[1]:
  309. while 1:
  310. print("检查到有联系人号码不相同:\n",p1.elem,"\n",p2.elem)
  311. print("请选择:\n"
  312. "1.合并号码\n"
  313. "2.分别保存\n")
  314. choi=input("输入选择: ")
  315. if choi=='1':
  316. l3.insert_elem_to_last(p1.elem)
  317. p3=l3.LocateElem(p1.elem)
  318. p3.elem[1]=p1.elem[1]+'、'+p2.elem[1]
  319. p2=p2.next
  320. break
  321. if choi=='2':
  322. l3.insert_elem_to_last(p1.elem)
  323. l3.insert_elem_to_last(p2.elem)
  324. p2=p2.next
  325. break
  326. else:
  327. print("输入有误,请重新输入")
  328. continue
  329. else:
  330. p2=p2.next
  331. p1=p1.next
  332. print("重复的信息有\n:",l3)
  333. print()
  334. #将剩余没有重复的加入l3
  335. p1=l1.head
  336. p2=l2.head
  337. p3=l3.head
  338. if p3!=None:
  339. while p1:
  340. if not l3.LocateElem_first(p1.elem[0]):
  341. l3.insert_elem_to_last(p1.elem)
  342. p1=p1.next
  343. while p2:
  344. if not l3.LocateElem_first(p2.elem[0]):
  345. l3.insert_elem_to_last(p2.elem)
  346. p2=p2.next
  347. if p3==None:
  348. l3=l1
  349. while p2:
  350. p3=l3.head
  351. while p3:
  352. if p2.elem[0]!=p3.elem[0]:
  353. l3.insert_elem_to_last(p2.elem)
  354. p3=p3.next
  355. p2=p2.next
  356. l1.ListClear()
  357. l2.ListClear()
  358. #l3排序后写入文件
  359. sortl=[]
  360. p=l3.head
  361. while p:
  362. sortl.append(p.elem)
  363. p=p.next
  364. sortl=sorted(sortl,key=toPinyin)
  365. p=l3.head
  366. i=0
  367. while p:
  368. p.elem=sortl[i]
  369. p=p.next
  370. i+=1
  371. print("合并后的通讯录为\n",l3)
  372. print()
  373. #写入文件
  374. first = ['姓名(names)', '电话号码(tel_number)', '分组(group)']
  375. f = open('connect.csv', 'a', encoding='utf-8',newline='')
  376. writer = csv.writer(f)
  377. writer.writerow(first)
  378. f.close()
  379. p=l3.head
  380. while p:
  381. f=open('connect.csv','a',encoding='utf-8',newline='')
  382. writer=csv.writer(f)
  383. writer.writerow(p.elem)
  384. p=p.next
  385. f.close()
  386. #主界面
  387. def choose():
  388. os.system("cls")
  389. devide = "--"
  390. print(devide * 40)
  391. print(" 1.查看通讯录\n"
  392. " 2.查看通讯录人数\n"
  393. " 3.查找联系人\n"
  394. " 4.模糊查找通讯录(输入姓名)\n"
  395. " 5.新增联系人\n"
  396. " 6.删除联系人\n"
  397. " 7.合并两个通讯录\n"
  398. " 8.退出\n"
  399. "-------------------------------------------------------------------------------------"
  400. "-----------------------------作者:华南农业大学 2021人工智能系 VIK------------------------"
  401. "-----------------------------如有使用请标明参考地址出处--------------------------------------")
  402. print(devide * 40, )
  403. #主函数
  404. if __name__=='__main__':
  405. l=LinkList()
  406. devide="--"
  407. choose()
  408. while 1:
  409. choiec=input("->请输入功能对应的序号,输入menu唤出功能菜单,按回车键结束: ")
  410. os.system("cls")
  411. if choiec== '1':
  412. os.system("cls")
  413. try:
  414. l.fun1()
  415. input("点击回车返回主界面")
  416. choose()
  417. except:
  418. print("未知错误,请重启选择菜单")
  419. continue
  420. elif choiec== '2':
  421. try:
  422. l.fun2()
  423. input("点击回车返回主界面")
  424. choose()
  425. except:
  426. print("未知错误,请重启选择菜单")
  427. continue
  428. elif choiec== '3':
  429. try:
  430. l.fun3()
  431. choose()
  432. except:
  433. print("未知错误,请重启选择菜单")
  434. continue
  435. elif choiec== '4':
  436. try:
  437. l.fun4()
  438. choose()
  439. except:
  440. print("未知错误,请重启选择菜单")
  441. continue
  442. elif choiec== '5':
  443. try:
  444. l.fun5()
  445. input("点击回车返回主界面")
  446. choose()
  447. except:
  448. print("未知错误,请重启选择菜单")
  449. continue
  450. elif choiec== '6':
  451. try:
  452. l.fun6()
  453. input("点击回车返回主界面")
  454. choose()
  455. except:
  456. print("未知错误,请重启选择菜单")
  457. continue
  458. elif choiec=='7':
  459. try:
  460. connnect()
  461. input("点击回车返回主界面")
  462. choose()
  463. except:
  464. print("未知错误,请重启选择菜单")
  465. continue
  466. elif choiec=='8':
  467. break
  468. elif choiec=='menu':
  469. os.system("cls")
  470. choose()
  471. continue
  472. else:
  473. print("***************************输入有误,请重新输入*****************************")
  474. print(devide*40)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/218411
推荐阅读
相关标签
  

闽ICP备14008679号