第四章的作业和实践题要论印象深刻无疑就是AI的那道题了。不得不说一开始看到题目的时候,我真的蒙了很久。
本题要求你实现一个简易版的 AI 英文问答程序,规则是:
1.无论用户说什么,首先把对方说的话在一行中原样打印出来;
2.消除原文中多余空格:把相邻单词间的多个空格换成 1 个空格,把行首尾的空格全部删掉,把标点符号前面的空格删掉;
3.把原文中所有大写英文字母变成小写,除了 I;
4.把原文中所有独立的 I 和 me 换成 you;
5.把原文中所有的问号 ? 换成惊叹号 !;
6.把原文中所有独立的 can you 换成 I can —— 这里“独立”是指被空格或标点符号分隔开的单词;
7.在一行中输出替换后的句子作为 AI 的回答
以上就是这道题的题目了。是不是有点蒙?虽然说是说一道题,实际上说是六道题都不夸张。
星期一下午上完课,我就打开了电脑开始琢磨这道题。在这里跟大家分享一下我一开始的思路。有一些不足,大家也见谅一下哈哈哈。
首先要确定一下数据结构。看到这道题,我思考了一下,要用字符串来做的,这显而易见。
但也从题目看到,这道题是有好几行的输入,而且是针对每一行进行处理的。因此,我们很有必要逐行逐行地输入,方便后面的处理。在这时我权衡了一下,一个办法就是弄一个二维数组,另一个办法则是重新定义一个类型。这个结构体中就可以打包一个数组或一个string 类的型。最终我决定使用后一个办法,毕竟比起二维的数组,一维的思路会更加清晰一点。
接下来就是进行一些简单的操作,逐行输入字符和完成第一个小要求输出字符串了。这操作比较简单我也就不多说了。但有一个比较重要的点。如图下:
在第一行输出后会有一个回车,此时如果没有将这个回车用字符吸掉,那么后面就会错乱了。因为运行时会将回车当做第一个字符串。一开始我就犯了这个错误,怎么样都是只能输入五行的字符。找了很久也没找到问题所在。这也还是我之前博客中提到的细节问题了。
接下来就开始处理其他的条件了。我粗略地看了一下,觉得空格的问题会在很大程度上影响后面的操作,而解决之后就不用再考虑空格问题,首先解决这个问题应该会比较划算。这么想着我就开始了。
消去空格有三个地方要消,一个是前面一个是中间,还有就是最后面的空格。
前面和中间的方法我就还是想了出来。一开始想的是数组移动,一次解决掉两个问题。后来发现实在是太繁琐了,要判断很多条件,而且前面空格和中间符号前空格并没有太大的关系。倒不如分开来进行解决,采取另一种移动的形式,从一个数组移到另一个数组。
1.消掉前面的空格可以理解为从非空格的字符开始移动到另一个数组。要找的就是非空格字符的首坐标。
2.消掉中间的空格,首先要消掉多余的空格,加下来要消掉符号前的空格。
我的想法就是先把第一个空格存储起来,再判断下一个字符,增加下标,直到下一个不为空格为止。如此就可以消掉多余的空格了。接下来就继续判断当前这个是不是为标点符号,倘若是就可以将新的字符数组下标减1(这里可以理解为删去了存进去的空格字符)
这里给的判断标点符号的方法实在有些蠢。但通过老师上课讲,我也进行了改进,可以利用判断是否独立的条件再加上该符号不是空格这两个条件就可以了
3.对于最后面的空格我实在没想到怎么处理。哈哈哈,不过上了课我现在还是可以一本正经地会了。经过前面对空格的处理,此时最后面的空格一定也只存储了一个,所以只需判断第j-1个字符是否为空格就行了。如果是空格就进行覆盖,不是就继续存储即可。
接下来就是解决大小写的问题了。这里要求把除了‘I’之外的所有大写字母变为小写。变为小写的函数之前学了strlwr函数,上课老师也讲了tolower函数。这都不是大问题。关键是需要判断‘I’的条件。开始我是先将全部变为小写,再遍历将‘i’改为‘I’。而这样做确是行不通的,因为题目是需要把原来本来为‘I’的字符保留不变,而现在却是把所有的‘i’都变为了‘I’。因此,需要在改小写时进行判断是否为大写字符且不为‘I’。
(如图:并非所有的i都是I)
对于剩下的三个要求,其实基本上就是同一类的问题的,同样的道理,也就可以一起解决了。
没听课的时候,我自己还是如除去空格一样的思路,就将原字符数组进行遍历判断修改后存进新的字符组中。而后来老师上课带我们尝试了直接判断后输出的方式,比起再建数组要更加简洁明了。
主要的思路就是对字符串进行遍历,看是否为题目所说的特殊条件,若是就进行特别输出,不是就直接输出。
当然这其中有很多细节要处理
1.对于是否独立的问题,前面也已经给出,采用isalone函数进行判断。只要前后都不是数字或者字母即为独立。
2.对于k-1,k+1,等条件要关注是否越界的问题。
如当k为0时,k-1就越界了。
说到这里,这道题总的思路就算是缕清了。其实细细分析了之后,也就没那么迷茫了。明白了题目的要求,条件与条件之间的关系,解决问题的顺序,使得思路更加地清晰明了。
通过解决对这道题的得到的收获还是挺多的吧,我觉得解决问题最重要的是明白自己究竟想要干什么。知道自己的目的,然后找到解体的方法,可能有多种,但通过对比也会发现某一种做法会更加的简单明了。通过不断对自己的思路和代码的改进也是在进步。当然光有思路也是不行的,很多细节都要注意到,往往出错的也都是细节。
上一次的目标我应该算实现了一部分吧,之前寒假写的推箱子的游戏中间有一个问题一直没解决,就是关于换地图的问题,需要读取text的文件进行更改。网上查到的函数我一直不太明白如何正确使用。而上课的时候老师讲了freopen函数(解决病毒问题中讲到的)
我就对我的代码修改了一下,也算解决了一个问题。上次说是想写一个新的小游戏,没实现,但解决了之前的问题也算还可以吧。
下一次的目标,我希望我可以掌握一下kmp算法以及将病毒的问题的程序学习一下并实践一下。