鱼C论坛

 找回密码
 立即注册
查看: 3831|回复: 21

[已解决]第17课:函数统计str,我的思路

[复制链接]
发表于 2021-1-8 15:47:24 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 Peteryo01223 于 2021-1-8 16:02 编辑

原题目:
编写一个函数 findstr(),该函数统计一个长度为 2 的子字符串在另一个字符串中出现的次数。例如:假定输入的字符串为“You cannot improve your past, but you can improve your future. Once time is wasted, life is wasted.”,子字符串为“im”,函数执行后打印“子字母串在目标字符串中共出现 3 次”。

注:小甲鱼的答案,我看了,能理解。目前想顺着我最初做题的思路,再尝试一下,因为我相信python足够灵活。

我最初的思路:
  1. def findstr():
  2.     a = input("请输入目标字符串:")
  3.     b = input("请输入子字符串(两个字符):")
  4.     a1 = a # 做个备份出来,便于稍后的切片操作
  5.     c = a1.index(b) # 定位首个子字符串
  6.     i = 0

  7.     while c:
  8.         i +=1 # 只要c为真,就给 i+1
  9.         a1 = a1[(c+1):] # 直接切除 a1 中首个出现的子字符串(即 那个b中的两个字符)以及它俩前面的全部字符,形成新的 a1
  10.     return i

  11. print("子字符串在目标字符串中共出d%次" % i )
复制代码


运行后,报错如下:
Traceback (most recent call last):
  File "C:/Users/user/Desktop/20210108d.py", line 13, in <module>
    print("子字符串在目标字符串中共出d%次"%i)
NameError: name 'i' is not defined


请高手指点,给出正确的code才好。谢谢


最佳答案
2021-1-8 17:02:21
Peteryo01223 发表于 2021-1-8 16:13
我又改了一下。好消息:不报错了。坏消息,统计结果不对。


由你的程序,可以看出你对字符串处理有两个知识点不扎实
第一,字符串备份写的不对,你这不是备份只是又起了一个名字,备份应该这么写:a1=a[:]
第二,对index的使用方法了解不够,1)index作用是查找子串的位置,是可以有三个参数的,第一个参数是子串,第二个参数是起始位置,第三个参数是结束位置,所以说没必要给字符串a备份,然后查找的时候一直切片,第二次查找的时候可以直接a.index(b,c+1);2)index只有在包含子串的时候有效,能得到返回值,若不包含子串,那么是会报错的。
所以有两种处理方法:一、依然使用index,将之放在try…except…中,抛出异常的时候,说明已经没有子串了,这时候return;二、不用index,改用find,find的作用和index基本一样,不同点就是没有找到的话,find返回-1,而index会报错
  1. #使用index
  2. def findstr():
  3.     a = input("请输入目标字符串:")
  4.     b = input("请输入子字符串(两个字符):")
  5.     i=0
  6.     try:
  7.         c = a.index(b) # 定位当下的首个出现的子字符串
  8.     except ValueError:
  9.         return i

  10.     while True:
  11.         i +=1
  12.         try:
  13.             c = a.index(b,c+1)
  14.         except ValueError:
  15.             return i

  16. print("子字符串在目标字符串中共出%d次" % findstr() )
复制代码
  1. #使用find
  2. def findstr():
  3.     a = input("请输入目标字符串:")
  4.     b = input("请输入子字符串(两个字符):")
  5.     i=0
  6.     c = a.find(b) # 定位当下的首个出现的子字符串
  7.     while c!=-1:
  8.         i +=1
  9.         c = a.find(b,c+1)
  10.     return i

  11. print("子字符串在目标字符串中共出%d次" % findstr() )
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2021-1-8 15:59:28 | 显示全部楼层
本帖最后由 昨非 于 2021-1-8 16:00 编辑

i是函数内部的局部变量,调用时是访问不了的
而且你的findstr函数也没调用啊
i既然作为返回值大可直接print函数里调用findstr()

(你这思路还挺清奇哈)
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-8 16:02:29 | 显示全部楼层
昨非 发表于 2021-1-8 15:59
i是函数内部的局部变量,调用时是访问不了的
而且你的findstr函数也没调用啊
i既然作为返回值大可直接pri ...

能帮我改改 code 么?如果思路对,该怎么写呀?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-8 16:05:06 | 显示全部楼层
昨非 发表于 2021-1-8 15:59
i是函数内部的局部变量,调用时是访问不了的
而且你的findstr函数也没调用啊
i既然作为返回值大可直接pri ...


我看了你的话,改了改,貌似成功了?!但是肯定有累赘的地方,并不简洁。

  1. def findstr():
  2.     a = input("请输入目标字符串:")
  3.     b = input("请输入子字符串(两个字符):")
  4.     a1 = a # 做个备份出来,便于稍后的切片操作
  5.     c = a1.index(b) # 定位当下的首个出现的子字符串
  6.     i = 0
  7.    

  8.     while c:
  9.         
  10.         i +=1 # 只要c为真,就给 i+1
  11.         a1 = a1[(c+1):] # 直接切除 a1 中首个出现的子字符串及前面的全部字符
  12.         return i
  13.         c = a1.index(b) # 针对切割后的a1, 再次定位当下的首个出现的子字符串

  14. print("子字符串在目标字符串中共出%d次" % findstr() )
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-8 16:05:25 | 显示全部楼层
我刚刚看了下你的思路,你定位到字串索引后,c在循环中没有变化,也就是while c是个死循环,不行啊
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-8 16:06:09 | 显示全部楼层
Peteryo01223 发表于 2021-1-8 16:05
我看了你的话,改了改,貌似成功了?!

但是我这边执行的时候死循环了,还是不行的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-8 16:07:56 | 显示全部楼层
昨非 发表于 2021-1-8 16:05
我刚刚看了下你的思路,你定位到字串索引后,c在循环中没有变化,也就是while c是个死循环,不行啊

我修改后,还是不对!统计一次可以,一旦统计多次,就报错。看来 while c,这里有问题。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-8 16:09:23 | 显示全部楼层
Peteryo01223 发表于 2021-1-8 16:07
我修改后,还是不对!统计一次可以,一旦统计多次,就报错。看来 while c,这里有问题。

你这return i的位置就不对
必须执行完while后再return才是最终结果
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-8 16:13:59 | 显示全部楼层
昨非 发表于 2021-1-8 16:09
你这return i的位置就不对
必须执行完while后再return才是最终结果

我又改了一下。好消息:不报错了。坏消息,统计结果不对。

  1. def findstr():
  2.     a = input("请输入目标字符串:")
  3.     b = input("请输入子字符串(两个字符):")
  4.     a1 = a # 做个备份出来,便于稍后的切片操作
  5.     c = a1.index(b) # 定位当下的首个出现的子字符串
  6.     i = 0
  7.    

  8.     while c:
  9.         i +=1 # 只要c为真,就给 i+1
  10.         a1 = a1[(c+1):] # 直接切除 a1 中首个出现的子字符串及前面的全部字符
  11.         c = a1.index(b) # 针对切割后的a1, 再次定位当下的首个出现的子字符串
  12.     return i

  13. print("子字符串在目标字符串中共出%d次" % findstr() )
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-8 16:14:08 | 显示全部楼层
本帖最后由 jackz007 于 2021-1-8 16:20 编辑

        数据输入和结果显示不应该分家,最好把数据输入挪出 findstr() 函数,这样做,可以让这个函数更加具有通用性。
  1. def findstr(a , b):
  2.     c = 0
  3.     i = a . find(b , 0)
  4.     while i != -1:
  5.         c += 1
  6.         i = a . find(b , i + len(b))
  7.     return c

  8. a = input("请输入目标字符串:")
  9. b = input("请输入子字符串(两个字符):")
  10. print("子字符串在目标字符串中共出 %d 次" % findstr(a , b))
复制代码

        运行实况:
  1. D:\0002.Exercise\Python>python x.py
  2. 请输入目标字符串:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
  3. 请输入子字符串(两个字符):aa
  4. 子字符串在目标字符串中共出 16 次

  5. D:\0002.Exercise\Python>
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2021-1-8 16:16:39 | 显示全部楼层
本帖最后由 昨非 于 2021-1-8 16:17 编辑

给你改对了
  1. def findstr():
  2.     a = input("请输入目标字符串:")
  3.     b = input("请输入子字符串(两个字符):")
  4.     a1 = a # 做个备份出来,便于稍后的切片操作
  5.     c = a1.index(b) # 定位当下的首个出现的子字符串
  6.     i = 0
  7.    
  8.     while c:
  9.         try:
  10.             i +=1 # 只要c为真,就给 i+1
  11.             a1 = a1[(c+1):] # 直接切除 a1 中首个出现的子字符串及前面的全部字符
  12.             c = a1.index(b) # 针对切割后的a1, 再次定位当下的首个出现的子字符串
  13.         except:
  14.             return i

  15. print("子字符串在目标字符串中共出%d次" % findstr() )
复制代码

测试结果:
  1. 请输入目标字符串:You cannot improve your past, but you can improve your future. Once time is wasted, life is wasted.
  2. 请输入子字符串(两个字符):im
  3. 子字符串在目标字符串中共出3次
复制代码


证明你的思路是可以的,只不过while c为真i+1这里不太对
事实上,你用index定位字串,然后i+1,定位后移的时候,会出现一个
  1. ValueError: substring not found
复制代码
的异常
也就是报错找不到字串了,也就是找完了的意思,循环中利用try except语句检测这个异常并返回此时的i就好了

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-8 17:02:21 | 显示全部楼层    本楼为最佳答案   
Peteryo01223 发表于 2021-1-8 16:13
我又改了一下。好消息:不报错了。坏消息,统计结果不对。


由你的程序,可以看出你对字符串处理有两个知识点不扎实
第一,字符串备份写的不对,你这不是备份只是又起了一个名字,备份应该这么写:a1=a[:]
第二,对index的使用方法了解不够,1)index作用是查找子串的位置,是可以有三个参数的,第一个参数是子串,第二个参数是起始位置,第三个参数是结束位置,所以说没必要给字符串a备份,然后查找的时候一直切片,第二次查找的时候可以直接a.index(b,c+1);2)index只有在包含子串的时候有效,能得到返回值,若不包含子串,那么是会报错的。
所以有两种处理方法:一、依然使用index,将之放在try…except…中,抛出异常的时候,说明已经没有子串了,这时候return;二、不用index,改用find,find的作用和index基本一样,不同点就是没有找到的话,find返回-1,而index会报错
  1. #使用index
  2. def findstr():
  3.     a = input("请输入目标字符串:")
  4.     b = input("请输入子字符串(两个字符):")
  5.     i=0
  6.     try:
  7.         c = a.index(b) # 定位当下的首个出现的子字符串
  8.     except ValueError:
  9.         return i

  10.     while True:
  11.         i +=1
  12.         try:
  13.             c = a.index(b,c+1)
  14.         except ValueError:
  15.             return i

  16. print("子字符串在目标字符串中共出%d次" % findstr() )
复制代码
  1. #使用find
  2. def findstr():
  3.     a = input("请输入目标字符串:")
  4.     b = input("请输入子字符串(两个字符):")
  5.     i=0
  6.     c = a.find(b) # 定位当下的首个出现的子字符串
  7.     while c!=-1:
  8.         i +=1
  9.         c = a.find(b,c+1)
  10.     return i

  11. print("子字符串在目标字符串中共出%d次" % findstr() )
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2021-1-8 17:13:35 | 显示全部楼层
jackz007 发表于 2021-1-8 16:14
数据输入和结果显示不应该分家,最好把数据输入挪出 findstr() 函数,这样做,可以让这个函数更加 ...

牛人,你太厉害了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-8 17:17:09 | 显示全部楼层
昨非 发表于 2021-1-8 16:16
给你改对了

测试结果:

学习了!第一次接触到 try 和 except 语法,很有用!谢谢谢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-8 17:18:42 | 显示全部楼层
本帖最后由 昨非 于 2021-1-8 17:23 编辑
Peteryo01223 发表于 2021-1-8 17:17
学习了!第一次接触到 try 和 except 语法,很有用!谢谢谢


小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-8 17:22:30 | 显示全部楼层
本帖最后由 Peteryo01223 于 2021-1-8 17:46 编辑
sunrise085 发表于 2021-1-8 17:02
由你的程序,可以看出你对字符串处理有两个知识点不扎实
第一,字符串备份写的不对,你这不是备份只是 ...


您解释得非常耐心,感谢,的确我的基础知识很差。同时,find 我接触很少, try/except 我之前没见过,慢慢在丰富我的理解中。再次感谢详解,受教了。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-8 17:24:07 | 显示全部楼层
昨非 发表于 2021-1-8 17:18
满意的话请设置为最佳答案

下次一定哈!多谢你。这次有个答案写得太详细了,实在是不能不给他一个“最佳”。下次一定给你。请高人您多多包涵。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-8 17:26:57 | 显示全部楼层
Peteryo01223 发表于 2021-1-8 17:24
下次一定哈!多谢你。这次有个答案写得太详细了,实在是不能不给他一个“最佳”。下次一定给你。请高人您 ...

没事,大佬回答得好,给他没毛病哈
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-8 17:33:10 | 显示全部楼层
本帖最后由 Peteryo01223 于 2021-1-8 17:47 编辑
sunrise085 发表于 2021-1-8 17:02
由你的程序,可以看出你对字符串处理有两个知识点不扎实
第一,字符串备份写的不对,你这不是备份只是 ...


多问一句:
#使用index,您的语句 while True,是如何保证没出现死循环的呢?Python怎么知道什么时候停?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-8 17:41:11 | 显示全部楼层
jackz007 发表于 2021-1-8 16:14
数据输入和结果显示不应该分家,最好把数据输入挪出 findstr() 函数,这样做,可以让这个函数更加 ...

我又比较了一下,您的结论最简洁、通用性最强!刚看懂。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-26 14:59

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表