C++中的输入输出都是通过流来进行的,而具体的输出输入都是通过对流进行操作来完成的,一般为定向一个流(重定向),清空流,向流里边添加新的元素。C++把输入输出看做字节流,输入时从字节流中抽取字节,输出时把字节插入到字节流中。
cin对象将标准输入表示为字节流,通常情况下用键盘来生成这种字节流,常用的cin输入发方法为cin>>abc;而istream类对抽取运算符进行了重载,是之可以识别这些基本类型,unsigned/signed char&, char&, short&, unsigned short&, int&,unsigned int&,long&, unsigned long&, long long &, unsigned long long &, float& double &, long double&;对于这些基本类型直接就用cin加抽取运算符>>就可以实现。有个问题就在于>>抽取符会跳过换行符且回忽略类似于空白,制表之类的字符,所以这样的一段程序是有问题的,这段代码里面的循环将会永远的跑下去,单纯地用这种方法进行对字符类数据的输入就出现了很大的问题。
而对于要输入一个字符串如果用cin>>input;这样的方法来输入一个字符串,则遇到空白换行,制表之类的,输入都会停止
1 char a; 2 int times=0; 3 cin>>a; 4 while(a!='/n') 5 { 6 cout<<a; 7 cin>>a; 8 times++; 9 } 10 cout<<times;
C++对字符串,字符和string类输入的时候常用的get(),getline()函数,他们被称为非格式化输入,因为他们只读取字符,包括空白 ,换行符, 制表符,等也不会进行数据转换,读到啥就是啥。
在istream里边定义的get()函数与getline()函数:
用get进行单字符输入,在有参数或者没有参数的情况下,get函数读取一个输入字符,不管这个字符是啥换行,制表都可以,直接读进去。
其中get(void)将字符转换成整形后返回,对于get(char&)函数返回一个指向的调用它的istream对象的引用,这样就可以使用类似于cin.get(a).get(b).get(c);的方式来读取,这其中要注意get不会忽略换行符,所以要注意换行符被不小心读进去的情况。
如果读取倒了文件尾,或者键盘输入的尾部等没东西可读的情况的时候,cin.get(ch);会返回false,其余正常情况返回的都是true。
特征 | cin.get(ch) | ch=cin.get() |
传输输入特征 | 直接赋值给ch | 把函数返回值赋给ch |
读取到字符之后函数返回至 | 指向istream对象的引用 | 字符编码,其实是int值 |
达到文件尾时函数的返回值 | 转换为false | EOF |
注:键盘输入仿真的文件尾与真正的文件尾效果一样
在istream中定义的get()函数一共有六项重载:使用的时候只要符合任意一种参数规则即可
1. int_type __CLR_OR_THIS_CALL get();//无参数,只读取一个字符,返回值为int型
2. _Myt& __CLR_OR_THIS_CALL get(_Elem *_Str, streamsize _Count);//接受两个参数,一个字符串首地址,一个int型的形参来控制最大读取字符数,为存放字符串末尾 //的/0,这个参数要比读取的字符串大一,该函数默认分界符为/n.
3. _Myt& __CLR_OR_THIS_CALL get(_Elem *_Str, streamsize _Count, _Elem _Delim);//与上边基本相同,不同之处在于这个函数分界符为自己定的_Delim.
4._Myt& __CLR_OR_THIS_CALL get(_Elem& _Ch);//接收参数为char型的引用,起作用就是把值直接赋给ch;
//在测试函数的时候有点发现,不能对字符串进行引用,因为数组是一个由若干个元素所组成的集合,所以无法建立一个数组的别名。
如果这块是 char &bbb = input[10]; //不能建立数组的引用。//这块效果就是对input[0]进行引用。
5._Myt& __CLR_OR_THIS_CALL get(_Mysb& _Strbuf);
6._Myt& __CLR_OR_THIS_CALL get(_Mysb& _Strbuf, _Elem _Delim);//除第一个函数外其他函数返回值均为指向调用它的istream对象的引用。
以上函数在使用的时候都要主意只能使用 cin.get (若干参数或者没有),get()函数在遇到换行符读取完字符时并不会读取换行符或者是本来的默认分界符,而这些东西都只会留在原始流之内,
char input[10] char ch; cin.get(input,10,'a'); cout << input << endl; cin.get(ch); cout<<ch<<endl;
输入sdsdsda
输出sdsdsd
a
在istream之中的getline()函数一共两项重载
1. _Myt& __CLR_OR_THIS_CALL getline(_Elem *_Str, streamsize _Count);2. _Myt& __CLR_OR_THIS_CALL getline(_Elem *_Str, streamsize _Count, _Elem _Delim);
这两个函数类似于get()函数中的2 、3重载,其不同之处在于getline()函数会自动丢弃换行符等分界符。
char input[10] char ch; cin.getline(input,10,'a'); cout << input << endl; cin.get(ch); cout<<ch<<endl;
输入 sdsdsda
输出sdsdsd
因为丢弃分界符,则分界符a被丢弃,下面的cin.get(ch)读到的是换行符,所以输出的时候就只是输出一个换行符。
单纯的应cin>>来输入一个string类字符串,则会在遇到空白,制表,换行等停止。
用getline()来读取string类, getline()在vs2010中函数定义在string文件中,共两个重构,且都为内联函数
1. template<class _Elem,
class _Traits,
class _Alloc> inline
basic_istream<_Elem, _Traits>& getline(
basic_istream<_Elem, _Traits>& _Istr,
basic_string<_Elem, _Traits, _Alloc>& _Str,
const _Elem _Delim)//使用的是自己定义的分界符,其参数为流定向类,第二个参数为输出目标string,第三个参数为自定义分界符
2. template<class _Elem,
class _Traits,
class _Alloc> inline
basic_istream<_Elem, _Traits>& getline(
basic_istream<_Elem, _Traits>& _Istr,
basic_string<_Elem, _Traits, _Alloc>& _Str)//默认的分界符为/n
这两个函数都没有字符串字符数上限的参数,因为string类会自己自动根据字符串的大小来调整大小。