明星猜猜猜(Name that Celebrity)
明星猜猜猜是一个针对基本String
操作的Java小项目。美国孩子可能会很喜欢,但中国孩子一般不大感冒。
要求是对于类似这样的明星名字:
Allan Alda
John Wayne
Gregory Peck
能够输出为这样的题目:
Allan Alda>>>lan A
John Wayne>>>hn Wa
Gregory Peck>>>egory P
然后根据半截名字猜出是哪个明星……
解题的话首先需要把规律分析出来,这个和那种小学奥数题目也有点类似,需要找一下共同的规律。第一行l,第二行h,第三行e,都是原来名字的第三个字母。那么结尾的话,正着数好像有点不一致,倒着数的话,就会发现是倒数第四个字母。确实不难。
对于Java的String
,有一些特殊之处需要初学者注意。
可以看到String
的index从0开始。所以第三个字母对应的index其实是2。同理执行length()
的结果会是10,那么事实上根据substring()
的定义,endIndex
应为7,即length()-3
。意思就是把index从7开始的部分切掉。
NameCelebrity.java
public class NameCelebrity { public static String name(String name) { return name.substring(2, name.length()-3); } public static void main(String[] args) { String s1 = "Allan Alda"; String s2 = "John Wayne"; String s3 = "Gregory Peck"; System.out.println(s1 + ">>>" + name(s1)); System.out.println(s2 + ">>>" + name(s2)); System.out.println(s3 + ">>>" + name(s3)); } }
首先注意我们定义了一个name()
,这样就不需要把这个String
变换的过程重复三遍(或者在真实案例里重复n遍)。我们定义函数是static
的,这样不需要instantiation也可以在main()
里调用。
其次name.substring()
其实本身是一个与name
不同的新String
,这样后面实际上可以同样继续无限制的加上一系列针对String
的操作。比如继续substring()
或者toUpperCase()
等等,非常灵活。
还有一个小点就是println()
里面的+
并不是我们通常意义上的加号,在这里执行的是合并String
的concatenation操作。请避免将其与算数+
混合起来。比如实际执行
1 + "1"
的时候,输出的结果会是"11"
而不是"2"
或者2
。事实上Java compiler内部执行的操作是先调用Integer
的toString()
,然后执行concatenation。而不是反过来把"1"
这个String
用parseInt()
转成Integer
。
当然对于真正的软件工程师而言,以上的代码是完全错误的。考虑到以下这种情况:
NameCelebrity.java
public class NameCelebrity { public static String name(String name) { return name.substring(2, name.length()-3); } public static void main(String[] args) { String s1 = ""; String s2 = "John Wayne"; String s3 = "Gregory Peck"; System.out.println(s1 + ">>>" + name(s1)); System.out.println(s2 + ">>>" + name(s2)); System.out.println(s3 + ">>>" + name(s3)); } }
就会发现当输入不合法时,整个程序会因为String index out of range
而在未执行完工作前就强制退出了。勉强可以接受的做法是以下这样:
public class NameCelebrity { public static String name(String name) { try{ return name.substring(2, name.length()-3); } catch(Exception e){ return ""; } } public static void main(String[] args) { String s1 = ""; String s2 = "John Wayne"; String s3 = "Gregory Peck"; System.out.println(s1 + ">>>" + name(s1)); System.out.println(s2 + ">>>" + name(s2)); System.out.println(s3 + ">>>" + name(s3)); } }
对于Exception
实际开发里有不同的处理方法。像我们这个例子里是可以无视然后继续工作的。如果是造成严重软件错误(比如内存泄漏)或者硬件错误(比如显卡像显示器发送硬件不支持的刷新频率),需要立即终止程序(见过Windows 10蓝屏(BSOD)没?)。如果是可能造成用户数据丢失(比如Word崩溃),需要尽最大可能保存用户数据。如果是在原子操作(比如银行转账,从我账户里扣了钱但是还没有把钱打到你账户里)过程中出现,需要把整个操作回滚到初始状态(不然我的钱就蒸发了……)。