cin.get()与此cin.getline()的底层区别?

yah00o5724 2007-04-28 03:56:25
请先看下面一段程序:

#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个帖子,仍然没有解决这个问提?我希望高人"同时"能给我一些关于缓冲区原理,写入设备原理等相关方面的解释,谢谢大家!!!
...全文
908 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
yah00o5724 2007-04-30
  • 打赏
  • 举报
回复
这个问题我终于明白了,非常感谢 ff5dq4 的热情帮助,你的8次回复,帖帖让我受益非浅.
没想到我在CSDN里发的第一张帖子就得到您这么热情的回复,这更坚定了我学好C++的信心!
当然还要感谢其他各位好友的回帖!感谢大家的热情帮助!
这个问题到此终于可以画上一个完美的句号了!谢谢大家!!!
ff5dq4 2007-04-30
  • 打赏
  • 举报
回复
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,以及非字符:'.' 后 停止读入,剩余深入留缓冲区

yah00o5724 2007-04-29
  • 打赏
  • 举报
回复
我是楼主,是一名C++初学者,很高兴ff5dq4() 又一次回答了我的问题,让我对这个问题有了更深的认识,受益颇丰.但还有一些地方不明白,希望您能帮我再次释疑.
=====================================================================================
你最后一次回复里提到 "cin.getline(a,5,'q'); 有个特点在你的输入字符长度大于等于5 就会认为是个非法的操作他会把cin流阻断, 就是在iostream 标志条上的 fail位设置为1,这样流就不能用了,所以你后面用的cin的语句无效".
我想问的是:
如果我把程序改成下面那样:
-----------------------------------------------------------------------------------
int main()
{
char a[5],b[5],c[5];
cout<<"input a:"<<endl;
cin.getline(a,5,'q'); //我输入1234后回车,1234/0被赋予a;getline()不会把换行符保留在
//缓冲区,那么此时缓冲区内已经是空.

cin.get(b,5,'q'); //???问题:按照你的说法,下面这两条cin的语句还是可以用的,但我为
cin.get(c,5); //什么还是没有机会输入,这时缓冲区内不是已经是空的了吗?
cout<<a<<endl;
cout<<b<<endl;
cout<<c<<endl;
return 0;
}



yah00o5724 2007-04-29
  • 打赏
  • 举报
回复
非常感谢 ff5dq4() ,由于你的帮助,对于cin.get()和cin.getline()我基本上已经没有问题了.
但是我还想问一下关于cin>>的一些问题,请先看下面一段程序:
=================================================================================
int main()
{

const int arsize=10;
char name1[arsize];
char name2[arsize];
int age;
char addr[arsize];

cout<<"what is your first name?";
cin.getline(name1,arsize);

cout<<"what is your last name?";
cin.get(name2,arsize);

cout<<"what is your age?";
cin>>age;

cout<<"what is your address?";
cin.get(addr,arsize);

cout<<"name:"<<name1<<','<<name2<<'\n'
<<"age:"<<age<<'\n'
<<"address:"<<addr<<'\n';

return 0;
}
---------------------------------------------------------------
what is your last name?yahoo //输入yahoo且回车
what is your last name?hoo //输入hoo且回车
what is your age?100 //输入100且回车
address: //问题??这里我为何无法输入?是否cin>>也会
Press any key to continue //置fial位为1


yuyunliuhen 2007-04-29
  • 打赏
  • 举报
回复
//test.cpp
//Compiler options : /GX
#include <string>
#include <iostream>
int main () {
std::string s,s2;
std::getline(std::cin,s);
std::getline(std::cin,s2);
std::cout << s <<'\t'<< s2 << std::endl;
return 0;
}

Actual Results:
Hello<Enter Key>
World<Enter Key>
<Enter Key>
Hello World

Expected Results:
Hello<Enter Key>
World<Enter Key>
Hello World
ff5dq4 2007-04-29
  • 打赏
  • 举报
回复
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); //这句又可以读取了
yuyunliuhen 2007-04-29
  • 打赏
  • 举报
回复
wonderful!
yah00o5724 2007-04-29
  • 打赏
  • 举报
回复
ff5dq4() ,你好!
你的每次回复,都让我有新的收获,但也让我发掘出新的问题,请看下面一段程序:
==========================================
int main()
{
char a[5],b[5],c[5];
cout<<"input a:"<<endl;       //假如输入:12q34q56q/n

cin.getline(a,5,'q');        //执行完这一步,缓冲区里剩下:34q56q/n

cin.get(b,5,'q'); //执行完这一步,缓冲区里剩下:q56q/n

cin.get(c,5,'q'); //这里与以前的程序有所变化;执行到这一步,c遇见的第一个字             //符就是分界符q,所以c的值应该为空啊!但实际是c的值为q56q .
//我还发现:这里换成cin.get(c,5);c的值也为q56q ;也就是说这             //两个操作在这里是没有区别的,用谁都一样.请解释一下!!


cout<<a<<endl;
cout<<b<<endl;
cout<<c<<endl;
return 0;

-----------------------------------------
(1)假如输入:12q34q56q
输出结果是:
12
34
q56q //问题:这里应该是空的才对啊!!
==============================================================================
(2)假如输入:12qq
输出结果是:
12
回车
回车
-----------------------------------------------------------------------------------
这里输入的第一个q被cin.getline()"抛弃"了,第二个q遇到cin.get(b,5,'q');没有被读取,继续留在缓冲区;当遇到cin.get(c,5,'q');也没有被读取,还是留在缓冲区里,所以b 和 c 的值都为空,这样的理解不知是否正确?
yuyunliuhen 2007-04-29
  • 打赏
  • 举报
回复
MARK
yah00o5724 2007-04-29
  • 打赏
  • 举报
回复

我用的是visual studio.net 2003,结果还是:q56q
我认为不是编译器 的问题,因为我输入12qq,结果你也看到了是正确的,这到底是什么 原因呢?
-----------------------------------------------------------------------------------
上面问题2中 cin.get(c,5,'q'); 为什么没有进行读取?
输入字符串比分配的空间长时,getline()和get()将把余下的字符留在输入队列中,而getline()还会设置失效位,并关闭后面的输入。 get()则不会,这和你说的有冲突!我说的对吗?
-----------------------------------------------------------------------------------
再问你一个问题?下面一段是我在网上找的:
"当getline()或get()读取空行时,将发生什么情况?最初的做法是,下一条输入语句将在前一条getline()或get()结束读取的位置开始读取;现在的做法是,当get()读取空行后将设置失效位(failbit),这意味着接下来的输入将被阻断,但可以用下面的命令来恢复输入:cin.clear(); "
----------------------------------------------------------------
能帮我解释一下这段话吗?还有get()会使fial位置1吗?
ff5dq4 2007-04-29
  • 打赏
  • 举报
回复
问题1 你说的:
“q56q //问题:这里应该是空的才对啊!!”

是对的

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


问题2 大致是这样的
不过cin.get(c,5,'q'); 根本没有进行读取
因为前一个 cin.get(b,5,'q'); 在读到q时候已经fial位置1了
所以cin.get(c,5,'q'); 无效
ff5dq4 2007-04-29
  • 打赏
  • 举报
回复
呵呵 ,我也只是个出学者

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

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

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

通过使用cin的成员函数 cin.clear() 可以清除fail位上的1为0
这样又可以使用cin流了
ff5dq4 2007-04-28
  • 打赏
  • 举报
回复
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");
}
yah00o5724 2007-04-28
  • 打赏
  • 举报
回复
我是楼主,首先我要感谢一下ff5dq4()的形象解释,你说的那些我已经明白了.但我还还是不知道 b 和c 到底有没有从缓冲区获得值?值是什么?为什么?能具体到这个程序吗?

dai_weitao 2007-04-28
  • 打赏
  • 举报
回复
回车紧跟在字符后面
cin.get(目标,大小)读取前面的数据后停止,回车继续留在缓冲区
cin.getline(目标,大小) 读取前面的数据后停止把回车删除掉

回车排在缓冲区最前面
cin.get(目标,大小)\0赋给目标,设置失效位,缓冲区被禁止读取,回车留在缓冲区.
cin.getline(目标,大小)\0赋给目标,把回车删除掉,结束此次读取.
friday5pm 2007-04-28
  • 打赏
  • 举报
回复
mark
taodm 2007-04-28
  • 打赏
  • 举报
回复
楼主是VC6,还没打sp6补丁吧?
lin_style 2007-04-28
  • 打赏
  • 举报
回复
cin.getline(a,5,'q');//只执行了这个
cin.get(b,5,'q');
cin.get(c,5);
cout<<a<<endl;
cout<<b<<endl;
cout<<c<<endl;
lin_style 2007-04-28
  • 打赏
  • 举报
回复
什么啊。是你代码有问题
加载更多回复(2)

65,212

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧