#include
using namespace std;
int main()
{
const int Asize = 20;
char name[Asize];
char dessert[Asize];
cout << "Enter your name:" <> name;
cout << "Enter your favorite dessert:" <> dessert;
cout << "I have some delicious " << dessert;
cout << "for you, " << name << endl;
return 0;
}
在没有输入你最喜欢的甜点的提示下,程序就把它显示出来了,然后立即显示最后一行。这是因为cin使用空白(空格、制表符和换行符)来确定字符串的结束位置,这意味着cin在获取字符串数组输入时只读取空格前的一个单词。读取该单词后,cin将该字符串放到数组中,并自动在结尾添加空字符。
为了能读取一行字符串输入,cin提供了一些面向行的类成员函数:getline()和get()。这两个函数都读取一行输入,直到到达换行符。然而,随后个getline()会丢弃换行符,而get()将换行符保留在输入序列中。下面详细介绍它们,首先介绍getline()。
面向行的输入:istream& getline(char *p, int n, char c)
getline()函数读取整行,它使用通过回车键输入的换行符来确定输入结尾。要调用这种方法,可以使用cin.getline()。该函数有两个参数。第一个参数是用来存储输入行的数组的名称,第二个参数是要读取的字符数量。如果参数是20,那么最多可以读取19个字符,余下的空间用于存储自动在结尾处添加的空字符。如果在读取n-1个字符之前遇到终止字符(第三个参数不写,默认为'\n'),则提前结束。getline()成员函数在读取指定数目的字符或遇到换行符时停止读取。
#include
using namespace std;
int main()
{
const int Asize = 20;
char name[Asize];
char dessert[Asize];
cout << "Enter your name:" <
getline(cin, inputLine),其中cin是正在读取的输入流,而inputLine是接收输入字符串的string变量的名称。需要注意的是,它不是类方法。
#include
#include // Header file needed to use string objects
using namespace std;
int main()
{
string name;
string city;
cout << "Please enter your name: ";
getline(cin, name);
cout << "Enter the city you live in: ";
getline(cin, city);
cout << "Hello, " << name << endl;
cout << "You live in " << city << endl;
return 0;
}
面向行的输入:istream& get(char *p, int n, char c)
另一个名为get()的成员函数,该函数有几种变体。其中一种变体的工作方式和getline()类似,它们接受的参数相同,解释参数的方式也相同,并且都读取到行尾。情况1:当输入的字符数小于n时遇到终结符,get()并不再读取并丢弃终结符,而是将其留在输入队列中。而getline函数将读取这个字符但是不存进p所指的数组中,而是将其丢弃。当然,两者都会在读取的字符串后面自动加上'\0'。假设我们连续两次调用get():
cin.get(name, Asize);
cin.get(dessert, Asize); //dessert没有内容
由于第一次调用后,换行符将留在输入队列中,因此第二次调用时看到第一个字符便是换行符。因此get()认为已到达行尾,而没有发现任何可读取的内容。如果不借助于帮助,get()将不能跨过该换行符。这时可以使用get()的另一种变体。使用不带任何参数的cin.get()调用可读取下一个字符(即使是换行符)。
cin.get(name, Asize);
cin.get();
cin.get(dessert, Asize);
另一种使用get()的方式是将两个类成员函数拼接起来:
cin.get(name, Asize).get();
之所以可以这样做,是由于cin.get(name, Asize)返回一个cin对象,该对象随后将被用来调用get()函数。同样,下面的语句将输入中连续的两行分别读入到数组name1和数组name2中,其效果与两次调用cin.getline()相同:
cin.getline(name1, Asize).getline(name2, Asize);
#include
using namespace std;
int main()
{
const int Asize = 20;
char name[Asize];
char dessert[Asize];
cout << "Enter your name:" <
空格行和其他问题
当getline()或get()读取空格时,将发生什么情况?当get()读取空行后将设置失效位。这意味着接下来的输入将被阻断,但可以用下面的命令来恢复输入:cin.clear();
情况2:另一个潜在的问题是,输入字符串可能比分配的空间要长。如果输入行包含的字符数比指定的多,则getline()和get()将把余下的字符留在输入队列中,对get()而言,可以用另一条读取函数来读取留在输入队列中的数据,也可以写一段代码将余下的字符清除。而getline()还会设置失效位,并关闭后面的输入。同样使用cin.clear()恢复输入。
#include
using namespace std;
int main()
{
cout << "What year was your house built?" <> year;
cout << "What is its street address?" <
用户根本没有输入地址的机会。问题在于,当cin读取年份,将回车键生成的换行符留在了输入队列中。后面的cin.getline()看到换行符后,将认为是一个空行,并将一个空字符串赋予address数组。解决的方法是,在读取地址之前先读取并丢弃换行符。这可以通过使用没有参数的get()和使用接受一个char参数的get():
cin >>year;
cin.get(); // or cin.get(ch);
也可以利用表达式cin >> year 返回cin对象,将调用拼接起来:
(cin >> year).get(); // or (cin >> year).get(ch);
#include
using namespace std;
int main()
{
cout << "What year was your house built?" <> year).get();
cout << "What is its street address?\n";
char address[80];
cin.getline(address, 80);
cout << "Year built: " << year <
补充的一点:C++中 "\n" 与 endl 的区别
"\n" 表示内容为一个回车符的字符串。std::endl 是流操作,输出的作用和输出 "\n" 类似,但略有区别。
std::endl 输出一个换行符,并立即刷新缓冲区。
cout << endl;
相当于
std::cout << '\n';
std::fflush(stdout);
由于流操作符 << 的重载,对于 '\n' 和 "\n",输出效果相同。
对于有输出缓冲的流(例如cout、clog),如果不手动进行缓冲区刷新操作,将在缓冲区满后自动刷新输出。不过对于 cout 来说(相对于文件输出流等),缓冲一般体现得并不明显。但是必要情况下使用 endl 代替 "\n"是个好习惯。对于无缓冲的流(例如标准错误输出流cerr),刷新是不必要的,可以直接使用 "\n"。