首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

cin.get()与此cin.getline()的底层区别?解决办法

2012-02-16 
cin.get()与此cin.getline()的底层区别?请先看下面一段程序:#includeiostream#includestringusingname

cin.get()与此cin.getline()的底层区别?
请先看下面一段程序:

#include   <iostream>
#include   <string>
using   namespace   std;

int   main()
{
      char   a[5],b[5],c[5];
      cout < < "input   a: " < <endl;
      cin.getline(a,5, 'q ');
      cin.get(b,5, 'q ');
      cin.get(c,5);
      cout < <a < <endl;
      cout < <b < <endl;
      cout < <c < <endl;
      return   0;

---------------------------
假如输入:123456
输出结果是:
1234//a   的值是:1234
/n      //b   的值是:/n               ??疑问--为什么是回车
/n         //c   的值是:/n               ??疑问--为什么是回车
Press   any   key   to   continue;
---------------------------
问题:我不明白b和c的值为什么是一个回车??????

我知道:
用getline,则 'q '被从缓冲区抛弃
用get,则 'q '仍然留在缓冲区

那么当我输入:123456,数据将先存在缓冲区中,当按下回车时,缓冲区里是:123456/n
共7个字符.
cin.getline(a,5, 'q ');将只读取1234,然后补 '\0 ',而把余下的三个字符56/n全部
"抛弃",此时缓冲区里已经没有任何字符了,那为什么
cin.get(b,5, 'q ');仍能得到字符/n;
cin.get(c,5, 'q ');也得到了字符/n;

不知道我的理解是否正确,还请各位高人不吝赐教?
注:我在网上搜这个问题,至少看了100个帖子,仍然没有解决这个问提?我希望高人"同时"能给我一些关于缓冲区原理,写入设备原理等相关方面的解释,谢谢大家!!!


[解决办法]
形象的说流对象(比如cin,cout)可以看着是一条运河,他架设于两个点(生产部门, 对外销售部门)之间,其中一个部门是主,另一个是从 ,而他们之间通过运河来传递产品(数据)

当主部门是生产部门(输出流):

生产部门生产出产品后然后,通知销售部门去运河等待

同时把产品整理好,分别装载进一长队运输船(数据序列),

然后起航,于是产品就被水运输(水流动)到了销售部门,然后产品就被销售部门进行展示与销售(屏幕显示)

当主部门是销售部门(输入流):

销售部门总是在顾客需要产品的时候,或本地库存不足等类似情况的时候,通知生产部门索取产品

然后生产部门将产品整理装载入船,运送过来

于是销售部门等着来一艘船,并卸载一次产品,直到最后一船的船主告之: "这是最后一船 "(数据结尾标记)

一些细节问题问题

如果生产部门一生产出一个商品就通知销售部门去运河接受货物,而每次销售部门专门耗费了大量人力组织的货物截取活动,却仅仅只能得到连一个最小的运输车都塞不满的产品,这样就得不偿失,于是双方协商后得到一个解决方案在运河的其中一边设立一个仓库部门,生产部门只要生产出了产品只管发到一个仓库部门,当仓库堆积满了,仓库部门就通知销售方来获取所有的产品(更新缓冲区),相反即使仓库没满,销售方也可以要求仓库发货,如果仓库货不够,仓库方就通知生产部门赶制产品(cin> > &a;总是先读取缓冲区里的数据,如果缓冲区里的数据没有结尾标识,则读完里面的数据后,再等待用户键盘的输入,直到结尾标识) ,而仓库好比流的缓冲区

当销售部门要求的产品和生产部门发送来的产品不一致的时候(cin> > int_value,却发送的char字符),则销售部门并停止获取产品,并立刻通知生产部门(failbit置1),直到生产部门认识到了错误情况,并回应(clear())
这里的通知,与回应,就是流的状态标识

[解决办法]
输入的字符超出限定参数规定的个数(超出大小)

cin.get(目标,大小) 读入规定字符,超出的字符留在缓冲区
cin.getline(目标,大小)读入规定字符并设置失效位failbit阻断输入队列

回车紧跟在字符后面
cin.get(目标,大小)读取前面的数据后停止,回车继续留在缓冲区
cin.getline(目标,大小) 读取前面的数据后停止把回车删除掉

回车排在缓冲区最前面
cin.get(目标,大小)\0赋给目标,设置失效位,缓冲区被禁止读取,回车留在缓冲区.
cin.getline(目标,大小)\0赋给目标,把回车删除掉,结束此次读取.
[解决办法]
int main()
{
char a[5],b[5],c[5];
cout < < "input a: " < <endl;
cin.getline(a,5, 'q ');

if(cin.fail()==1) cout < < "流已经设置fail位,所以cin以后的读取无效,用cin.clear()可以清除\n ";system( "pause ");

cin.get(b,5, 'q ');
cin.get(c,5);
cout < <a < <endl;
cout < <b < <endl;
cout < <c < <endl;
return 0;

system( "pause ");
}

------解决方案--------------------


cin.getline(a,5, 'q '); 有个特点 在你的输入字符长度大于等于5 就会认为是个非法的操作
他会把cin流阻断, 就是在iostream 标志条上的 fail位设置为1,这样流就不能用了
所以你后面用的cin的语句无效

通过使用cin的成员函数 cin.clear() 可以清除fail位上的1为0
这样又可以使用cin流了

[解决办法]
呵呵 ,我也只是个出学者

cin.getline(a,5,);//遇到回车停止,回车作为分界符
cin.getline(a,5, 'q ');// 把分界符由回车替换成 'q ',而回车不再是分界符,只是普通的字符

所以你输入1234 后回车,相当于 有5个字符 '1 ', '2 ', '3 ', '4 ', '回车字符 '传递给&a
这样当然会引起 fail职1


[解决办法]
问题1 你说的:
“q56q //问题:这里应该是空的才对啊!!”

是对的

我把你的程序试了下 c是空, 不知道你用的什么编译器 我用的gcc
2003应该也是这个结果,


问题2 大致是这样的
不过cin.get(c,5, 'q '); 根本没有进行读取
因为前一个 cin.get(b,5, 'q '); 在读到q时候已经fial位置1了
所以cin.get(c,5, 'q '); 无效
[解决办法]
input a:
12q34q56q //输入且回车
12 // 结果
34 // 结果

请按任意键继续. . .

---------------------
这是我2003运行的结果
程序原封不动的复制过去运行的

应该是编译器的问题


get(目标,大小) 是在读取的时候,如果第一个字符是回车 则置fail 为1 ,
比如:

get(&a,5); //输入12后回车, 缓冲区里将会有3个字符 1 2 回车
//1 2读入a 回车留在缓冲区里
get(&b,5); //这句第一个读到的字符就是回车,所以立刻置fial位(即failbit)为1
//回车依然在缓冲区
get(&c,5); // 因为 failbit)为1 这句无效
cin.clear(); // 清除失效位:failbit 恢复为0

cin.get();// 读取缓冲区的回车,
// 缓冲区现在为空 ,且没有失效位

get(&d,5); //这句又可以读取了
[解决办法]
what is your age?100 //输入100且回车,

//补充:回车还留在缓冲区的

cout < < "what is your address? ";
cin.get(addr,arsize); //会接到回车 造成fail置1

-----------------------------------------
> > 操作符号 在输入的类型不匹配的情况 fail置1

比如 int a;
cin> > a ; 如果你输入的是字符就会造成类型不匹配

-----------------------------------------
关于> >

cin> > T类型数据变量: 输入数据超过T类型的大小 会产生未知效果

下面的输入情况都假设在避免了超出数据类型大小的范围进行的
int a;
cin> > a // 当读入遇到 非0到9 的数字字符后 停止读入,剩余深入留缓冲区

double a
cin> > a; //当读入遇到 非0到9,以及非字符: '. ' 后 停止读入,剩余深入留缓冲区

热点排行