天天看点

关于cin的get()和getline()成员函数

cin是使用空白(空格,制表符,换行符)来确定字符串的结束位置这意味着cin在获取字符数组时只读取一个单词。读取该单词后cin自动在其结尾增加空字符。

这有时候很方便,有时候有使我们烦恼:如果我要输入一句话来存入字符串中呢?

要将整条短语而不是一个单词作为字符串输入,需要采用另一种字符串读取方法。

具体地说,需要采用面向行而不是面向单词的方法。

istream的类cin提供了一些面向行的类成员函数:getline() and get()

这两个函数都读取一行输入,直到遇到换行符为止。

不同的是getline()随后将丢弃换行符,而get()将换行符保留在输入序列中。

下面先说说getline():

geiline的使用方法是cin.getline(char*, int)。

该函数有两个参数,第一个是你要储存的目标,第二个是最多读取多少位字符。如,若该参数为29,则最多读取28个字符。余下的空间是留给空字符的。

getline成员函数在读取指定字符数或者遇到换行符时停止读取。

注意,可以认为getline()读取换行符,但随后将换行符丢弃,换成空字符。

关于get():

get成员函数有多重变体,其中有一种与getline相似,他们接受的参数个数相同,参数的解释也相同,并且都读取到行尾。

值得注意的是,get函数并不读取并丢弃换行符,而是将其留在输入序列中。这种特点如果不留意的话,会造成一些难以预料的麻烦。

下面举个栗子,当我们连续两次使用get():

cin.get(name, size);
cin.get(hobby, size);
           

第一次调用get()时,将换行符留在输入队列中,因此第二次调用时看到的第一个字符便是换行符,因此第二个get函数会认为已经到达行尾,便不再读取以下内容。

这个时候我们需要借助get函数的另一种变体,即不带任何参数的get函数:cin.get(),它可以读取下一个字符,即使是换行符,因此可以用它来处理换行符。

它的调用形式可以是以下两种:

//第一种:
cin.get(name, size);
cin.get();
cin.get(hobby, size);
cin.get();
           
//第二种:
cin.get(name, size).get();//之所以可以这样做,是因为cin.get(name, size)返回一个cin对象,
              //这个对象随后被用来访问get成员函数。
cin.get(hobby, size).get();
           

More:在使用cin之后使用getline的情况,如:

int year;
char name[];
cin >> year;
cin.getline(name, );
           

这种情况下name中储存的不是我们输入进去的字符串,而是空字符串。原因是cin在读取year之后将换行符留在了输入队列,getline一开始就遇到换行符。

而我们以前连续调用cin不会产生读取空字符串的情况,是因为cin会自动忽略掉开头的换行符。

另外再做一下说明:

getline(char*, int)成员函数和get(char*, int)成员函数不适合于C++的string类。

或者这么说,适用于string类的getline函数并不是istream的成员函数,而是其友元函数,因此如果要读取一行字符串到string对象中,需要使用下面的格式:

getline(cin, str);
           

而get函数不适合于string类对象。

为什么string类的对象搞特殊呢?这是历史原因啦。

关于cin.get()函数的补充:

get()函数还有两种变体

一种是接受一个char类型作为参数:

cin.get(ch);
           

该函数返回一个cin对象。

由于cin在需要的情况下可以转为bool值,所以可以用cin.get(ch)函数来判断输入是否到达结尾:

cin.get(ch);
while (cin) {
     ……
     cout << ch;
     cin.get(ch);

}

//或者采用更简洁的表示:
while (cin.get(ch)) {
     cout << ch;
}
           

P.S.这里的“输入到达结尾”是指从键盘模拟的EOF,Windows下是Ctrl + z + Enter

另一种是

该函数不接受任何参数,它的作用是读取下一个字符并赋值给ch。

当然这个表达式的值是赋值运算符左边的值,即ch;

所以这个函数也可以用来判断输入是否到达结尾:

while (ch != EOF) {
    cout << ch;
    ch = cin.get();
}
//或者采用更简洁的表示:
while ((ch = cin.get()) != EOF) {   //这个表达式的值是赋值运算符左边的值,即ch;
    cout << ch;
}
           

在希望逐字节地读取文本文件或文本输入时,可以使用这两个函数。

为什么不是cin >> ? 因为cin将自动地忽略空格,换行符,制表符,有时候,我们并不期待这种事情的发生。

下面是这两个函数的区别:
           
属性 cin.get(ch) ch = cin.get()
传递输入字符的方式 赋给参数ch 将函数返回值赋给ch
用于字符输入时函数的返回值 istream对象(执行bool转换后为true) int类型的字符编码
到达EOF时函数的返回值 istream对象(执行bool转换后为false) EOF

另外,cin.get(ch)还有一个好处就是它可以拼接起来,如:

cin.get(ch1).get(ch2);
           

最后,指出下列cin成员函数也可以判断输入是否到达结尾:

cin.fail()
cin.eof()
           

继续阅读