通讯录最首要的功能,就是添加联系人,使联系人列表从无到有。考虑实际使用时,应能批量添加联系人,故操作3的过程应为:
提示用户输入联系人信息->用户确认输入完毕->将信息写入文本中->提示用户添加成功。
这其中最难的一步就是“如何确认用户输入完毕”,网上有一个很简单也很经典的例子:
初看似乎很符合逻辑,但这样带来的问题是:程序将会一直等待用户输入而不退出循环。
这涉及到流结束标志的问题,C++ primer中似乎没有提及。事实上,之前提到的cin输入缓冲区,是
行缓冲
(注:当在输入和输出中遇到换行符时,执行真正的I/O操作。即先将输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作,典型代表是键盘输入数据)。当从键盘上输入一串字符并按回车后,这些字符会首先被送到输入缓冲区中存储。每当按下回车键后,就会检测输入缓冲区中是否有了可读的数据,还会对是否有作为流结束标志的Ctrl+Z 或者 Ctrl+D 键作出检查,其检查的方式有两种:阻塞式以及非阻塞式。
(注:阻塞式检查方式指是指只在回车键按下之后才对此前是否有 Ctrl+Z 组合键按下进行检查,非阻塞式样指的是按下 Ctrl+D之后立即响应的方式。)
Windows系统中一般采用阻塞式检查 Ctrl+Z,而Unix/Linux系统下一般采用非阻塞式的检查Ctrl+D。阻塞式检查的特点是:
如果输入缓冲区中有可读的数据,则不会检测 Ctrl+Z。用开头的代码作为示例,结果如下:
我的理解是这样:ctrl+z是一个组合键,在计算机内部,它应被映射成一个
值或者说编码,这个编码很可能会出现在正常的输入流里面,所以终端不应该从正常的输入里面去检测有没有这个值。常规的方法应该是,如果某一次的完全输入就
是这个编码值,就把它解释成EOF(EndOfFile)送给接受输入的C++程序。所以把ctrl+z放到正常输入的末尾时,它会被当成正常的输入,而
不会被解释成EOF。
明白了这些,就应该在提示信息中说明如何退出:
cout<<"在新的一行输入Ctrl+Z并回车结束输入。"<<endl;
而在通讯录中,我采用的是依据此原理的另一种办法。
由于MSDN中对getline的解释太多太多,这里就不多作说明了。从提示信息里也可以看出这么做的思路:
1、若不输入退出信息,则一直等待用户输入。
2、用户直接输入回车,相当于输入一个空行,而换行符会被getline()过滤掉,即退出循环。