#include "stdafx.h"
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
const int ArSize=20;
char name[ArSize];
char dessert[ArSize];
cout<<"Enter yout name:\n";
cin>>name;
cout<<"Enter your favorite dessert:\n";
cin>>dessert;
cout<<"I have some delicious "<<dessert;
cout<<" for you."<<name<<endl;
return 0;
}
注意看下面我运行的输入:
当我输入Alistair Dreeb的时候,甚至没有对“Enter your favorite dessert ”做出反应,程序便把它显示出来了,然后立即显示最后一行。
cin是如何确定已完成字符串输入的呢?
由于不能通过键盘输入空字符,因此cin需要用别的方法来确定字符串的结尾位置。cin使用空白(空格、制表符和换行符)来定字符串的界。这意味着cin在获取字符数组输入时只读取一个单词。读取该单词后,cin将该字符串放到数组中,并自动在结尾添加空字符。
这个例子的实际结果是,cin把Alistair作为第一个字符串,并将它放到name数组中,这把Dreeb留在输入队列中。当cin在输入队列中搜索用户喜欢的甜点时,它发现了Dreeb,因此cin读取Dreeb,并将它放到dessert数组中。
每次读取一个单词通常不是最好的选择。所以需要采用另一种字符串读取方法。具体地说,需要采用面向行而不是面向单词的方法。istream中的类(如cin)提供了一些面向行的类成员函数:getline()和get()。两个函数都读取一行输入,直到到达换行符。然而,随后getline()将丢弃换行符,而get()将换行符保留在输入序列中。 getline()函数读取整行,使用回车键输入的换行符来确定输入结尾。调用这种方法,使用cin.getline()。该函数有两个参数。第一个参数是用来存储输入行的数组的名称,第二个参数是要读取的字符数。如果这个参数为20,则函数最多读取19个字符,余下的空间用于存储自动在结尾处添加的空字符。getline()成员函数在赌气指定数目的字符或遇到换行符时停止读取。getline()函数每次读取一行,通过换行符来确定行尾,但不保存换行符。相反,在存储字符串时,它用空字符来替换换行符。
get()函数,有几种变体。其中一种变体的工作方式与getline类似,但get并不再读取并丢弃换行符,而是将其留在输入队列中。假设连续两次调用get():
cin.get(name, ArSize);
cin.get(dessert, ArSize);
由于第一次调用后,换行符将留在输入队列中,因此第二次调用时看到的第一个字符便是换行符。因此get()认为已到达行尾,而没有发现任何可读取的内容。如果不借助于帮助,get()将不能跨过该换行符。幸运的是,get()有一种,不带任何参数的cin.get()调用读取下一个字符(即使是换行符),的变体。因此可以用它来处理换行符,为读取下一行输入做好准备。
cin.get(name, ArSize);
cin.get();
cin.get(dessert, ArSize);
另一种使用get()的方式是将两个类成员函数拼接起来(合并),如下所示
cin.get(name, ArSize).get(); //concatenate member functions
cin.get(name, ArSize)返回一个cin对象,该对象随后将被用来调用get()函数。
注意:有些C++的老版本没有实现不接受任何参数的get()变体,但实现了接受一个char参数的get()变体。要使用该变体(而不是没有参数get()),需要首先声明一个char变量:
char ch;
cin.get(name, ArSize).get(ch); getline()使用起来简单些,但get()使得检查错误更简单些。
当getline()或get()读取空行时,将发送什么情况? 最初的做法是,下一条输入语句将在前一条getline()或get()结束读取的位置开始读取;但当前的做法是,当get()(不是getline())读取空行后将设置失效位(failbit)。这意味着接下来的输入将被阻断,但可以用下面的命令恢复输入:
cin.clear();
如果输入行的字符数比指定的多,则getline()和get()将把余下的字符留在输入队列中,而getline()还会设置失效位,并关闭后面的输入。
另一个问题是,输入字符串可能比目标数组长。