C++中cin.get(),cin.getline(),cin>>,gets(),cin.clear()使用总结
1.cin.get() 实质:类istream所定义对象cin的重载成员函数
用于读取单字符 istream& get(char&) int get(void) 用于读取字符串 istream &get(char*,int) istream &get(char*,int,char)
1.1 istream& get(char&)
Point1 返回一个指向用于调用它的istream类引用,可以读取空格符,制表符,换行符(以下对这三种字符统称空白)。如下所示分别输入三种字符时照样读取。这一点不同于cin>>。其将跳过空白,无法读取。如下所示输入的三个字符依次是空格符制表符和换行符。
Point2 由于返回的是调用对象cin,故cin.get()的读取还可以这样写 cin.get(ch1).get(ch2)>>ch3; 先将第一个字符(包括空白)给ch1返回调用对象cin。代码缩减为cin.get(ch2)。接着第二个字符(含空白)给ch2。接着代码缩减为cin>>ch3,此时将下一个非空白键字符给ch3。如下图所示:输入的字符依次为为空格符,制表符,‘6’。
Point3 如果cin.get(char&)到达文件结尾,它不给参数赋值,此时还将调用setstate(failbit)导致cin的结果为false,也就是说,可以将存在有效输入作为while循环的条件。如下:
char ch; while(cin.get(ch))//若存在有效输入,返回值为对象cin,判断结果为true {expression……; }
1.2 int get(void)
Point1 能够读取空白(空格,制表,换行)赋值给字符变量,返回类型为int。使用方法 char ch; ch=cin.get(); Point2 不能够使用如1.1中cin.get().get().get()……的形式来简写读取多个字符,原因为cin.get()返回为int值而并非对象。但下面的写法是正确的:
char ch1; cin.get(ch1).get();此时先返回对象cin,程序缩减为cin.get()。这里程序将读取并丢弃输入流中第二个输入字符(包含空白)。如下所示。依次输入为“chb”的结果;
实际上,在cin这个对象里,有一个储存字符的流,可以想象成缓冲区,事实上是cin里封装的一个东西.当我们在程序上输入字符后,对象cin获得了我们输入的字符。例如获得"chb回车",然后再通过cin.get()把流里面的第一个字符'c'抽取并从输入流中去掉,赋给ch1,这时,cin里储存的流的数据为"hb回车",此时cin.get(ch1).get()缩减为cin.get(),程序将抽取字符“h”并将其从输入流中去掉。这是输入流中剩下“b回车”,b被读取赋ch2。
Point3 一旦到达文件尾(不管是真正文件尾还是模拟的文件尾),cin.get(void)将返回值EOF---iostream中提供的符号常量(值为-1)。因此也可以用作控制条件;如下:
int ch;//注意声明为char,EOF可能无法用char类型来表示 while((ch=cin.get())!=EOF) { expression;……}
总结:希望程序检查每一个输入的字符(包括空白,尤其是换行符'\n'),请用get(),而需要跳过空白,可用抽取运算符“>>".get().类似C语言中的getchar(),类似的cout.put()类似putchar()。
1.3 istream &get(char*,int)和 istream &get(char*,int,char)
第一个参数为放置存储字符串的内存单元的地址,第二个参数为比需要读取的字符数大1的int值(显然额外的字符用于自动添加的字符串的结尾空字符),第三个字符为分界符,表示读到此不在读,若此处缺省即第一种情况,默认分界符为换行符。get()读到换行符或者分界符或者达到需要读取字符的数目后后立即终止读入。 如图输入"abcdEFG空格H制表I*^j换行"。"abcd"存储进str1,但分解字符'E'没有被读入并且仍旧留在输入流中(getline()也不读入但是会将其从输入流中删除)。E被读入到指针p所指向的空间,这里注意到“空格和制表均被被读取”。
2. istream &getline(char*,int) istream &getline(char*,int,char)
get()和getline()的区别是,前者将分界符保存在输入流中,后者则抽取并丢弃。如下图所示,分界符’E‘被丢弃。同样的,空格符和制表符被正常读入。这里对分界符做两种情况下的区分说明,倘若没有定义分界符,即get()和getline()为两个参数的情况,那么分界符缺省定义为换行符'\n';倘若定义了分解符,假设为‘\*’,即get()和getline()为三个参数的情况,那么换行符将作为一个正常字符输入,这一点在从外部文件中读取数据时值得注意。假设外部txt文件存储有一个二维char数组(3*100)的值(分3行),使用ifstream读入的时候,要考虑iftream.get()在分界符定义了的情况下将会将换行符读入,可能造成错误。
并且这里一定要考虑。getline()从输入流中提取并删掉分解符,而get()则只提取不删掉,尤其当分界符缺省为'\n'时,分界符会被写入下一个字符串的第一个位置。这里也有getline(cin,str1)一类的用法。包含于“#include<string>”。如下:
#include<iostream> #include<string> using namespace std; void main () { string str; getline(cin,str); cout<<str<<endl; } 输入:jkljkljkl 输出:jkljkljkl 输入:jkl jfksldfj jklsjfl 输出:jkl jfksldfj jklsjfl
3.cin>>
不管是输入字符或者字符串,所有空白(空格符,制表符,换行符)均被跳过(从输入流中抽取并删去但不写入字符或者字符串)。这一点区别于前两种输入方法,因为最起码空格符和制表符正常读取。如下图的输入流中含空格符和制表符。为了看清楚每一次具体的输出,用“-”来标示。不想略过空白字符,那就使用 noskipws 流控制cin>>noskipws>>data;
4.gets()
原型为char*gets(char*buffer);输入的时候以换行符作为结束,空格键和制表符正常写入。由于此函数不会检查是否溢出,应保证buffer空间足够。如果溢出,多出来的字符将被写入到堆栈中,这就覆盖了堆栈原先的内容,破坏一个或多个不相关变量的值。这个事实导致gets函数只适用于玩具程序。
5.cin.clear()
cin>>发生错误输入的时候,failbit被设置为1,只有用clear()将failbit修改到原来的状态0,输入才得以继续。
注意输入的是"12*34制表78换行",抽取运算符号>>在碰到错误输出时候,该错误字符仍旧留在输入流中,否则最后输出的就是”8“了,这里cin.get()会抽取并从输入流中删去错误的输入字符,保证输入得以继续。cin.peek()函数能够从输入流中提出一个字符,但是不会删去该字符,一般做字符检查之用。
6.cin.peek()
该调用形式为cin.peek() 其返回值是一个char型的字符,其返回值是指针指向的当前字符,但它只是观测,指针仍停留在当前位置,并不后移。如果要访问的字符是文件结束符,则函数值是EOF(-1)。其功能是从输入流中读取一个字符 但该字符并未从输入流中删除若把输入流比作一个 栈类 那么这里的peek函数就相当于栈的成员函数front 而如果cin.get()则相当于栈的成员函数pop。
#include "stdafx.h" #include"iostream" using namespace std; int main() { int s[3]; int i=0; while(i<3) { if(cin.peek()=='#') cin.get(); cin>>s[i]; i++; } cout<<s[0]<<" "<<s[1]<<" "<<s[2]; }
若输入12#34356#,则输出12 34 56
本文部分参考自 C++中cin、cin.get()、cin.getline()、getline()、gets()等函数的用法