教她写代码的那些日子 5 字符串

一个人下定决心去做一件事的话,一定会表现出极大的热情来。她的确是下定决心要学好写程序了,这从她表现出来的超高热情就能看出来。热情的表现之一就是下班后不急着回家了,而是拿着她的笔记本电脑到我的工位让我给她讲解写程序;热情的表现之二就是有时大半夜的会给我发微信,问我书上的某些练习题该怎么做。而我也很乐意在下班后和她呆在一起,因为我回家也是一个人待着,相较之下,和她一起待在办公室,对我来说真的是莫大的幸福了。

“戴老师,你看看我写得对不对?”那天晚上都12点了,她发来她写的那个我给她留的课后作业。

uploading.4e448015.gif

“写得还行。“看了她发过来的代码截图,我说,“这么晚了,你还在学习啊。”

“是呀。”她说,“要多练习嘛。”

“嗯,早点休息吧。”我打着哈欠,在微信上给她发出这几个字。

我确实是很困了,以致发出那几个字以后,就不知不觉睡着了,第二天早上才看到她发过来的“好”和晚安的动画表情。

由于晚上太困,没有仔细看她发过来的代码截图,今天仔细看了,才发现了一些问题,于是在下班后,开始学习新内容之前,我就和她说起我发现的问题。

“你昨晚写的代码,有些问题。”我说。

“是呀。”还没等我说出问题在哪里,她就接过我的话说,“本来想请教你来着,可是猜想你睡了,所以就没来得及问你。”

于是,她打开她的笔记本电脑,翻出她昨晚写的程序来,然后说出她自己早已发现的问题:“我这个程序只能判断出5位数,如果更多位怎么办,不可能把这个else if一直写下去吧。”

“那你有什么想法没?”我问。

“没有,昨晚我想着想着就睡着了,才发现写代码真的挺废脑力的。”

“那看到计算结果,你能数出来多少位吗?”

“这个肯定能啊,我好歹是上过幼儿园的啊。”

当然,上过幼儿园就会数数了,我不禁笑了起来。

”哈哈,知道你上过幼儿园。“我笑着说,”那你发现没有,一个只有一位的整数,每乘以10,位数就增加一位。”

“是这样,可是这和写程序有关系吗?”她有些不解地看向我。

“你仔细想想。”我不打算直接给她答案。

“嗯,我想想。”她陷入了深深的思考。

都说认真做事的男人最帅,但我发现认真思考的女人,也真的很美。

她在认真思考,而我一时没事可做,索性就认真地欣赏起她的这种美来,于是就出现这样一幅定格画面:她用手撑着头,眼睛有些发直,在她旁边,我侧身看着她,像雕塑一样一动不动。

“哈,我知道了。”她突然地发出声音,把我下了一跳。

”你怎么了?“她大笑着说,显然我一激灵的反应将她逗笑了。

”没怎么。“我有些不好意思,希望她没有发现我一直盯着她看吧。

”你说说你想到什么了。“我接着说。

于是她认真地说起她的想法来:”把一个整数循环除以10,直到为0为止,计算除了多少次,就知道这个整数是多少位了。“

”哈哈,没错。“我说。

”等我改下代码。“她说着,就去修改代码了。

uploading.4e448015.gif

编译运行:

uploading.4e448015.gif

编译后,她反复运行程序,输入各种整数,然后再去数结果的位数和计算机输出的位数是不是相同。

”哈哈,全正确,太有成就感了。“在把程序运行了不知多少次后,她满足地说。

“其实,电脑也是上过幼儿园哦。”等她享受完她的成就感后,我说。

我这一句没头没脑的话,让她愣了一下,随即她就明白过来,我是在揶揄她那句上过幼儿园的话。

“你是想说电脑像我一样聪明呢,还是想说我和电脑在一个智商水平啊?”她佯装愠怒地说。

“不不,我是说电脑也会数数的。”我连忙求饶道。

“怎么说?”

“那就该今天的主角出场了,你猜是什么?”我故作神秘地说。

“快说是什么?”

“字符串。”

“这个我知道,就是一串字符串起来,对不对?”

她显然已经看过书上关于字符串这一章节了,所以才会对字符串这个概念不陌生,并能说出她对字符串的理解。

“对,其实,我们一直在用字符串。你刚刚程序里面那个‘请输入一个整数:’就是一个字符串。”

“那确实是一串字符,可是这和让电脑数数有什么关系呢?”

“既然字符串是一串字符,那是不是有长度呢?”我问。

“对,好像字符串有一个计算长度的操作来着。”说着,她拿出书来翻着。

“所以,将1到n相加的结果转换成字符串,然后用字符串的计算长度的操作来计算出长度就是这个整数的位数了。”我在她翻书之际接着说。

“找到了。”她翻到了讲字符串操作的那一页说。

“那么试试这个方法呗。”

“可是怎么将一个整数转换成字符串呢?”她有些犯难。

“这个简单啊,用加号加上一个空字符串就好了,就像你刚刚写的程序里面那样。”我指着她电脑上那句输出结果的代码说。

“哦哦。”她说着改起代码来。

uploading.4e448015.gif

编译运行:

uploading.4e448015.gif

“哈哈,这样简单多了。”她高兴地说。

“字符串还有其他一些操作,你知道吗?”我问。

“知道一些,你再讲讲吧。”

“那我们还是来看几个例子吧。”我说,因为从示例中学习无疑是最高效的。

于是,经过短暂的一个思考后,我说:“假如给你一个邮箱地址,你怎么判断它是不是格式正确的邮箱地址?”

“我想想。”她说着,拿出纸笔来,一边写,一边念叨着:“邮箱地址的格式是前面一串字符,接着跟一个@,最后是一个网址。”

“是这样的一个字符串就是邮箱地址。”她指着纸上她写出的一个邮箱地址,擡起头来看着我说,意思是问我她说得对不对。

“没错,邮箱的一般格式为:用户名@邮箱服务器域名。我们可以从4个方面来验证:1是否包含@字符,2@字符是不是只有一个,3字符.是不是在@字符后面,4是不是以.com结尾。”我肯定了她的想法,并进行了扩展。

”嗯,好像是这样。“她说。

”那我们来写程序吧。“我说。

“好啊。”她说,然后新建了一个文件后,看着我不说话。

“写啊。”我说。

“怎么写?”她说。

我明白过来,她在等着我给她说怎么写。

“好吧,我来写,你来看。”我说,我终于想起来是我要给她讲字符串的一些用法的。于是,我从她手上接过笔记本电脑,写起这个验证邮箱地址的程序来:

uploading.4e448015.gif

“你看,写起来很简单的。”写完后我说。

这句话的背后意思是,这么简单的事情其实不需要我出手的,她显然听出来我话里的意思,脸上有了一些委屈和不悦。

”对于你来说是简单,可我是什么都不懂的小白啊。“她说。

”对对,我应该站在你的角度来看问题才对。“我连忙认错,然后又说:”那你看看这个程序,有什么不懂的,你说出来,我给你解答。“

”嗯,我看看。“她脸上的不悦已经烟消云散,这自然让接下来的一问一答在友好和轻松的氛围中顺畅进行着。

“咦,那个双斜杠那行是干什么的?”

“哦,双斜杠后面的都是注释。注释就是在源码中添加的一些备注说明,不会被编译到程序里面的。嗯……,这个注释的作用呢,主要是方便别人在看代码的时候容易理解代码的意思。其实更大的用处是留给自己看的,因为写程序的人,在时间久了的时候会经常忘了当时写这些代码是干嘛的。”

“诶,还真是,有这个注释,一看就看明白了这些代码是在干嘛了。不过,为什么atIdx等于-1就是没有找到@呢?”

“这个indexOf这个方法是从前向后查找指定的字符或者字符串,如果找到了就会把指定的字符或字符串在被找的字符串中的位置返回回来,如果没找到就返回-1,所以这里判断一下返回结果是不是-1就知道字符串中是不是有@这个字符了。对应的lastIndexOf是从后向前面查找,这个不用我解释了吧?”

“嗯,这个我懂了,从前向后查和从后向前查,查到的@的位置相同,说明整个字符串中只有一个@,因为如果有多个的话,这两种查法结果肯定不一样。不过,那个return是什么意思?”

“return是返回的意思。返回的意思呢,就是退出当前正在执行的方法,返回到调用它的地方继续执行。这里因为是在main方法中,而调用main方法的是系统,所以整个程序就退出了,返回到系统了。至于方法的一些东西,后面会专门学习的。”

“嗯,我没什么问题了。”

“那toLowerCase和endsWith是干什么的?”这回换成我问问题了。

“这个看字面意思就知道了啊,toLowerCase是将字符串中字符全部换成小写,endsWith是判断是不是以某个字符串结尾。”

“完全正确。”我说,“这个例子只用到这些字符串操作的方法,还有很多其他的你看看书就知道了,书上应该有一个表格列出这些方法。”

“书上是有这么一个表格。”在我说话的时候,她已经从书上找到了那个表格,但随即脸上就流露愁容,“不过,这么多内容我怎么记得住啊。”

“记这些干什么?”

“不记吗?那要用到这些怎么办?”

“你傻啊,要用的时候,百度一下不就好了。”说着我打开百度,在输入框中输入“java 截取字符串”,然后就出来一大堆截取字符串的内容。

“原来如此。”她一副发现天大秘密的表情。

“什么原来如此?”

“我原以为你们程序员都好厉害,这么厚一本书的内容都记得清清楚楚,原来是靠百度的啊。”

“所以啊,不要觉得写程序有多难。”我乘机鼓励她,并厚着脸皮夸了下我自己,“不过我还是很厉害的,我知道怎么百度。”

“嗯,你厉害,脸皮也厚得厉害。哈哈。”她说完忍不住笑出声来。

我也笑了起来,我是有点不好意思的笑。

“验证邮箱地址还有一个很简单的方法,你知道是什么吗?”等她笑完了,我说,转移了关于我脸皮厚的话题。

“不知道。”她一副虚心求教的样子看着我说。

“用正则表达式。”我说,同时开始修改刚刚那个验证邮箱地址的程序:

uploading.4e448015.gif

”是不是比刚刚那个简洁很多。“写完后我说。

”就这么一两行代码就搞定了?“她看了代码,觉得不可思议。

”对啊,这就是正则表达式的魅力所在。“

”那快给我讲讲这个正则表达式。“

”正则表达式是一个用于描述字符串规则的工具,或者说是记录文本规则的代码。“我试图给正则表达式是什么下一个定义,但好像不太成功,这从她那一脸茫然就能看出来。

所以我不得不回到刚刚验证邮箱地址的例子中来,于是我接着说:”还是来看刚刚那个例子吧。在这个例子中,邮箱地址的规则是这样的:1、以1个或多个字类字符(字母、数字和下划线)开头;2、紧接着是一个@;3、再后面是多个字母数字加点的组合;最后是一个com结尾。“

说到这,我停了下来,给她一些思考的时间。

”嗯,邮箱地址的格式的确是这样的。“她思考了以后说。

”既然规则是固定的,那么我们就用一个字符串来表达出这么一个规则,然后去验证输入的字符串是不是符合这个规则,符合就是邮箱地址,不符合就不是邮箱地址。这个表达规则的字符串就是正则表达式。关于表达式的常用语法我们还是来看看书吧。“说着,我拿过书,翻到讲正则表达式那个章节,递给她看。

字符的取值范围

1.[abc] : 表示可能是a,可能是b,也可能是c。

2.[^abc]: 表示不是a,b,c中的任意一个

3.[a-zA-Z]: 表示是英文字母

4.[0-9]:表示是数字

 

简洁的字符表示

^:匹配输入字符串开始的位置

$:匹配输入字符串结尾的位置

.:匹配任意的字符

\d:表示数字

\D:表示非数字

\s:表示由空字符组成,[ \t\n\r\x\f]

\S:表示由非空字符组成,[^\s]

\w:表示字母、数字、下划线,[a-zA-Z0-9_]

\W:表示不是由字母、数字、下划线组成

 

数量表达式

1.?: 表示出现0次或1次

2.+: 表示出现1次或多次

3.*: 表示出现0次、1次或多次

4.{n}:表示出现n次

5.{n,m}:表示出现n~m次

6.{n,}:表示出现n次或n次以上

 

逻辑表达式

1.XY: 表示X后面跟着Y,这里X和Y分别是正则表达式的一部分

2.X|Y:表示X或Y,比如"food|f"匹配的是foo(d或f),而"(food)|f"匹配的是food或f

3.(X):子表达式,将X看做是一个整体

 

她接过书,一会儿看看书,一会儿看看电脑屏幕,再歪着头思考一会儿。过了几分钟的时间,她终于像是恍然大悟了。

”哈哈,我明白了。“她说,”这个正则表达式还真是个好东西,用它来验证字符串真是太方便了。“

”你真的这么快就弄懂了?“我有些怀疑,因为当初我学这个的时候就花了很长时间才搞懂的,所以我是准备好好给她解释一番的。

”嗯,懂了。“她很肯定的回答。

”那我出几个题目考考你。“

”好啊,你出。“

”电话号码的正则表达式怎么写?“

“嗯,电话号码是一个3位或4位的区号,再加这个横杠,再加一个8位的号码。”她一边念叨着,一边在纸上写。

”写好了。“她说,然后我看到了她写的正则表达式:

^(\d{3}|\d{4})-\d{8}$

"不错,很对。”我说。

看来她真的掌握了,但我还是有点怀疑,她的学习能力如此强吗?我决定让她再多写几个来看看。

“网址的正则表达式怎么写?”我说。

她写:

^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"\"])*$

“Ip地址的正则表达式怎么写?”我说。

她写:

(\d+)\.(\d+)\.(\d+)\.(\d+)

“邮政编码的正则表达式怎么写?”我说。

她写:

^[1-9]\d{5}$

“好吧,我真是佩服你的学习能力了,这么快就掌握了正则表达式。”我说。

“哈哈,承蒙老师夸奖了,还是老师教得好。”她笑着说,脸上有一些自豪。

“好了,我们就不要再互相吹捧了吧。既然你学得这么快,那么我们继续后面的内容吧。”我觉得每次我们这样互相吹捧都挺搞笑的。

“我还有一个问题,”她突然说道,“^(匹配输入字符串开始的位置)和$(匹配输入字符串结尾的位置)这两个符号有什么意义,好像写不写也不影响字符串的验证啊。”

“嗯,光是做字符串格式的验证加不加这两个字符似乎没什么影响,但是用来在一个很长的字符串找出特定格式的字符串就有区别了。例如,要从一个很长的字符串中找出里面的所有电话号码,你想想怎么写程序?”这也是正则表达式经常用到的场景,正好给她讲讲。

“哎呀,你就别卖关子了,就直接给我讲吧。”

“好吧,就刚刚那个找电话号码的例子,我写个程序,你看了就会明白加不加^和$这两个字符的区别了。”

于是,我拿过电脑,一通敲击键盘,程序已经写好:

uploading.4e448015.gif

编译运行:

uploading.4e448015.gif

“看出来不同没?”程序运行后,我问她。

“我想想。“她回答。

我不再说话,她需要一些时间自己去领悟,学习终究还是自己思考后得来的才深刻。她就一直盯着电脑屏幕,而且保持一个姿势不动,这让我产生了时间停止的错觉。

“哈,我懂了。”随着她的声音传入我的耳朵,时间又开始流动起来。

“那你说说。”我说。

“匹配输入字符串的开始位置,就是匹配找到的字符串必须在被查找字符串的开始位置。匹配输入字符串的结尾位置,意思是匹配找到的字符串必须在被查找字符串的结尾位置。所以你刚写那个例子,第二个表达式只找到开头的电话号码,第三个表达式只找到最后一个电话号码,而最后一个表达式一个电话号码都没找到,因为没有一个电话号码是既在开始位置又在结尾位置的。”

“你这样理解也没有错,不过...”我本想给她讲讲我的理解的,但转念一想,她已经有自己的理解了,我再给她说我的理解,这会搅乱她脑海中建立起来的概念,于是我止住,没有往下说了。

“不过什么?”

“没什么。”

“没什么是什么?”

“没什么就是你太聪明了,不用我讲你就能领悟这么深奥的东西。”我笑着说。

“这话我爱听,不过我本来就聪明啊。”她也笑。

“那你这么聪明的话,我们来做一个有挑战的例子吧。”

“好啊,什么例子?”她表现出来很大的兴趣来。

“假如有一段文字,里面包含很多数字,现在要计算这些数字的总和是多少,该怎么做。”

“这叫有挑战吗?用正则表达式找出这些数字,然后加起来不就好了。”

“那就写一下看看了。”

“看着。”她说完就开始敲起代码来。

她写的代码:

uploading.4e448015.gif

编译运行:

uploading.4e448015.gif

“咦,怎么不对呢?”看到运行结果,她大惑不解地看向我。

“哈哈,你不是说没有挑战的吗?”我笑了起来。

“你就别笑我了,快看看是怎么回事。”

“好呢,且让我给你改上一改。”

我改过的代码:

uploading.4e448015.gif

编译运行:

uploading.4e448015.gif

“正确了,还是你厉害。”看到正确的运行结果,她有些悻悻地说。

“其实你没写出来是很正常的,因为这里有一个知识点你没学到。”我安慰她。

“我想也是,像我这么冰雪聪明的人,要不是有知识盲区,怎么可能难到我。”她复又自负起来。

“哈哈,其实你的脸皮也不薄啊。”我笑到。

“你才脸皮厚。”她佯装愠怒到。

“是是,我们还是来看看这个让你打脸的知识点吧。”我也不知怎么应对她的“怒火”,于是乖乖求饶到。

“还记得前面讲的变量的类型吗?”我问她,得到肯定的回答后我继续说,“字符串这个类型在做加法运算的时候它是把两个字符串拼接成一个字符串,所以你那样直接用字符串相加自然会得到一个更长的字符串而已。只有double、int这样的数字类型的变量相加才会进行算数运算,所以我们要先将数字字符串转换成数值变量再进行相加。”

“所以那个Double.parseDouble就是把字符串转换成double类型?”

“对,你说得没错,除了这个,还有Integer.parseInt用于将字符串转成int类型,Long.parseLong转成long等等,这个你也不用强记,知道就行了,需要用的时候直接百度就出来了。”

“我懂,不记得就百度嘛。”她不怀好意地笑着。

我知道她又在嘲笑我凡事就知道百度,不过这就是程序员的做事方式嘛,所以我也不在意的笑笑。

“嗯,类型转换,我记着了。”她认真地说,不待我说什么,她又说:“那个%.2f是干嘛的?”

“那是字符串的格式化。”我说,“又一个知识盲区,对吧?”

“知道还不快讲。”她说。

“字符串的格式化就是…”我突然不知道该怎么讲了,有很多东西自己心里明白是什么,可就是表达不出来,我似乎有严重的语言表达障碍。

“是什么?”她扑闪着那双灵动的大眼睛看着我说。

“嗯,就是一些数据按照一定格式转换成字符串。”我整理了一下思绪说,“就像这里,我们要让金额显示两位小数,所以就用%.2f这个格式字符来代表一个两位小数的数字。然后在执行String.format这个方法的时候就用后面的变量去替换%.2f,并且是按照它的格式进行替换,最终得到一个格式化后的字符串。”

她茫然地摇头:“你在说些什么呢?一点都不懂。”

“这个怎么解释呢?”我不自觉地挠着头,不知道是我表达有问题,还是她理解有问题,我想还是我表达的问题吧,所以我的大脑高速运转,只为找出一个能让她明白的表达方式。

最终我说:“这么说吧,你现在要定义一个字符串,但是这个字符串有些地方你暂时不知道是什么内容,于是你就用一些特殊的符号去把位置占上,再然后用String.format这个方法把那些特殊的符号换成具体的内容。”

“这么说的话,我应该明白了,但是这个地方直接用加号将金额拼接进去就好了啊,干嘛还这么复杂,弄一个%.2f去占着位置,后面又去替换?”她终于说她明白了,这让我舒了一口气。对于新问题,以她现在的好学,也是能理解的。

“这就是格式化的意义所在了,假设金额是一个整数的话,直接拼接就没有后面的小数位了。用格式化的话,因为我们设置的格式是两位小数,所以不管金额变量是不是整数,也不管小数的位数是多少位,都会转成两位小数的字符串,然后再替换。”

“哦,这样啊。”她不太相信地说。

“不然你试试。”我说,我想让她自己改程序验证。

于是在她把程序改动并执行了几次后,她说:“好吧,你说得一点没错。”

“那是,我怎么会错呢。”我有些得意地笑着说。

“是是,你是老师,我是学生嘛。”她说,顿了一下她又说:“今天学太多了,要好好消化一下。”

“是要好好消化一下,回去多做一些练习。”我附和着。

“啊,都这么晚了。”她看了看时间说,“我们回家吧。”

“好,走,下班回家。”我说。

于是,我们一道回家,这是第一次有机会和她一起回家,虽然我就住她家附近,回家路径也一样,但以前从没一道回家过,即便看到她在前面,我也没有勇气追上去。但今天她却和我一起走在回家的路上,而且我预感以后会一直这样,这或许是对我教她写程序的回馈吧。不管怎样,我依然是无比开心的,脸上却极力装着波澜不惊的样子。

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章