cin.ignore()的用法 cin.clear() cin.setstate()

  • cin.ignore()

basic_istream& ignore(streamsize _Count = 1, int_type _Delim = traits_type::eof());
function: Causes a number of elements to be skipped from the current read position.
Parameters:
_Count, The number of elements to skip from the current read position.
_Delim, The element that, if encountered before count, causes ignore to return and allowing all elements after _Delim to be read. (引用msdn)
这个函数用来丢弃输入缓冲区中的字符,第一参数定义一个数,第二个参数定义一个字符变量。下面解释一下函数是怎样执行的:函数不停的从缓冲区中取一个字符,并判断是不是_Delim,如果不是则丢弃并进行计数,当计数达到_Count退出,如果是则丢弃字符退出。例:cin.ignore(5, ‘a‘); 函数将不断从缓冲区中取一个字符丢弃,直到丢弃的字符数达到5或者读取的字符为‘a‘。下面我们看个程序例子:
程序10:
#include <iostream>
using namespace std;
int main ()
{
cin.ignore(5, ‘a‘);
return 0;
}
测试一输入:
c[enter]
c[enter]
c[enter]
c[enter]
c[enter]
程序结束。
【分析】程序开始时缓冲区是空的,cin.ignore()到缓冲区中取数据,没有则请求从键盘输入,每次从键盘输入一个字符,如果不是‘a‘则丢弃,所以该测试中共输入了5次,直到计数达到5。

测试二输入:
c[enter]
c[enter]
a[enter]
程序结束。
【分析】前面两个字符不是‘a‘丢弃且计数没达到5,第三次输入为‘a‘, 丢弃该字符程序结束!

丢弃一个字符:
我们看看这个函数的默认值,第一个参数默认为1,第二个参数默认为EOF。所以cin.ignore()就是丢弃缓冲区中的第一个字符,这在程序中也是比较常用的!我们回过头看看程序5,程序5中用cin.get()读取字符,第一次读取时用回车符结束,而get函数不丢弃回车符,所以回车符仍残留在缓冲区中,导致第二次读取数据直接从缓冲区中取得回车符!这与我们最初的用以是不相符的,既然cin.get()不会自动丢弃输入结束时的回车符,这里我们学会了ignore()函数,我们就可以自己手动求其回车符啊!所以程序5可以这样改动:
程序11:
#include <iostream>
using namespace std;
int main()
{
char c1, c2;
cin.get(c1);
        cin.ignore(); // 用该函数的默认情况,丢弃一个字符,即上次输入结束的回车符
cin.get(c2);
cout<<c1<<" "<<c2<<endl;   // 打印两个字符
cout<<(int)c1<<" "<<(int)c2<<endl; // 打印这两个字符的ASCII值
return 0; 
}
测试一输入:
a[Enter]
b[Enter]
输出:
a
b
97 98
【分析】这样程序就正常了!

清空整个缓冲区:
其实该函数最常用的方式是这样的,将第一个参数设的非常大,将第二个参数设为‘\n‘,这样就可以缓冲区中回车符中的所有残留数据,因为一般情况下前面输入残留的数据是没有用的,所以在进行新一次输入操作前将缓冲区中所有数据清空是比较合理。
如:cin.ignore(1024, ‘\n‘); 
或者:cin.ignore(std::numeric_limits<std::streamsize>::max(), ‘\n‘);

  • cin.clear()  cin.setstate()

再来看看输入状态标记位、状态测试函数、状态设置函数之间的关系:

  输入状态标记位常量有以下几个:

  标记位常量

  


  常量


  含义


  failbit标记位的值


  eofbit标记位的值


  badbit标记位的值


  转化为10进制


  ios::failbit


  输入(输出)流出现非致命错误,可挽回


  1


  0


  0


  4


  ios::badbit


  输入(输出)流出现致命错误,不可挽回


  0


  0


  1


  2


  ios::eofbit


  已经到达文件尾


  0


  1


  0


  1


  ios::goodbit


  流状态完全正常


  0


  0


  0


  0

  下面来解释这张表格:

  ios::failbit    ios::badbit    ios::eofbit    ios::goodbit均为常量,它们任何一个都代表了一种流状态,因此称为“输入状态标记位常量”。

  比如,ios::failbit表示的是流状态为

  流的failbit标记位值为1,eofbit标记位值为0,badbit标记位的值为0。

  始终牢记:failbit,badbit,Eofbit组成了流状态

  注意:它们不是failbit、badbit、eofbit、goodbit这四个标记位的存贮变量。

  我们可以用输出语句来验证:

  cout << ios:: failbit << endl;

  cout << ios:: eofbit << endl;

  cout << ios:: badbit << endl;

  cout << ios:: goodbit << endl;

  输出的结果为:

  4

  2

  1

  0

  同样是将3个标记位视为二进制数转化为十进制的原理。

  下面分析clear()函数:

  cin.clear(ios::failbit);

  使 得cin的流状态将按照ios::failbit所描述的样子进行设置:failbit标记位为1,eofbit标记位为0,badbit标记位为0。无 需担心goodbit标记位,failbit、eofbit、badbit任何一个为1,则goodbit为0。(goodbit是另一种流状态的表示方 法)

  cin.clear(ios::goodbit);

  使得cin的流状态将按照ios::goodbit所描述的样子进行设置:failbit标记位为0,eofbit标记位为0,badbit标记位为0。此时goodbit标记位为1,从另一个角度表示cin的流状态正常。

  因此clear() 函数作用是:将流状态设置成括号内参数所代表的状态,强制覆盖掉流的原状态

  再来分析一下setstate()函数:

  与clear()函数不同,setstate()函数并不强制覆盖流的原状态,而是将括号内参数所代表的状态叠加到原始状态上。

  比如,假设cin流状态初始正常:

  cin.setstate (ios::failbit);      //在cin流的原状态的基础上将failbit标记位置为1

  cin.setstate (ios::eofbit);     //在上一步结束的基础上,将cin流状态的eofbit标记位置为1

  两条语句结束后,cin的faibit标记位和eofbit标记位均为1,badbit标记位为0

  对比clear()函数的效果:

  cin.clear (ios::failbit);      //将cin的流状态置为ios::failbit所描述的状态

  cin.clear (ios::eofbit);     //将cin的流状态置为ios::eofbit所描述的状态

  两条语句结束后,cin的eofbit标记位为1,而failbit标记位和badbit标记位为0

  即使两种情况,在执行完各自的第一条语句后,cin的流状态情况相同,但当执行完第二条语句,本质区别就显露出来。

  最后来看看如何利用rdstate()函数和输入状态标记位常量来判断输入流的状态:

  #include <iostream>

  using namespace std;

  int main()

  {

  int a;

  cin>>a;

  cout<<cin.rdstate()<<endl;

  if(cin.rdstate() == ios::goodbit)

  {

  cout<<"输入数据的类型正确,无错误!"<<endl;

  }

  if(cin.rdstate() == ios::failbit)

  {

  cout<<"输入数据类型错误,非致命错误,可清除输入缓冲区挽回!"<<endl;

  }

  system("pause");

  return 0;

  }

  利用前面所讲的rdstate() 函数返回值原理和输入状态标记位常量表,不难理解:

  rdstate() 函数返回当前流对象的failbit、eofbit、badbit3个标记位状态的十进制值

  输入状态格式常量也是failbit、eofbit、badbit3个标记位状态的十进制值

  比如cin流状态读取错误,即failbit标记位为1,eofbit标记位为0,badbit标记位为0,则:

  cin.rdstate()的返回值为4,而格式常量ios::failbit的十进制也是4

  因此,if(cin.rdstate() == ios::failbit) 判断为Ture

  因此程序当中的两个if语句能有效识别出流状态

  再来看看有些许不同的程序:

  #include <iostream>

  using namespace std;

  int main()

  {

  cin.setstate(ios::failbit);

  cin.setstate(ios::eofbit);

  cout<<cin.rdstate()<<endl;

  if(cin.rdstate() == ios::goodbit)

  {

  cout<<"输入数据的类型正确,无错误!"<<endl;

  }

  if(cin.rdstate() == ios::failbit)

  {

  cout<<"输入数据类型错误,非致命错误,可清除输入缓冲区挽回!"<<endl;

  }

  system("pause");

  return 0;

  }

  输出结果为:

  6

  请按任意键继续...

  原因为何?

  cin流状态被设置成failbit标记位置为1,eofbit标记位置为1,badbit标记位为0

  那么cin.rdstate()的返回值二进制为110,十进制为6,即输出6。

  参照输入状态标记位常量表:

  ios::goodbit的二进制为000,十进制为0,因此if(cin.rdstate() == ios::goodbit)判断为False

  ios::failbit的二进制为100,十进制为4,因此if(cin.rdstate() == ios::failbit)判断为False

  然后system("pause"); 语句使得输出         请按任意键继续...

  很有意思吧,cin对象明明failbit标记位为1,但表达式cin.rdstate() == ios::failbit却是False,这就是原因。

  rdstate()函数与输入状态标记位常量的对比是严格按照数值对比的。

时间: 2024-10-08 21:08:19

cin.ignore()的用法 cin.clear() cin.setstate()的相关文章

[转]cin.clear()、cin.sync()和cin.ignore()的用法

cin.clear()是用来更改cin的状态标识符的. cin.sync()是用来清除缓冲区的数据流的. 如果标识符没有改变那么即使清除了数据流也无法正常输入,反之亦然,因此两者要联合起来使用.下面是一个使用的例子: #include<iostream> using namespace std; int main() { int a; cout<<"输入一个字母:"<<endl; cin>>a; //int型变量中放了char型数据,fa

cin.ignore()函数的用法

cin.ignore(a,ch)方法是从输入流(cin)中提取字符,提取的字符被忽略(ignore),不被使用.每抛弃一个字符,它都要计数和比较字符:如果计数值达到a或者被抛弃的字符是ch,则cin.ignore()函数执行终止:否则,它继续等待.它的一个常用功能就是用来清除以回车结束的输入缓冲区的内容,消除上一次输入对下一次输入的影响.比如可以这么用:cin.ignore(1024,'\n'),通常把第一个参数设置得足够大,这样实际上总是只有第二个参数'\n'起作用,所以这一句就是把回车(包括

C++ cin输入流 详细用法

我们来看下下面这段代码: #include <iostream> #include <vector> #include <cstdlib> int main() { int num = 0; std::vector<int> ivec; do { std::cout << "please input some numbers:" << std::endl; while (std::cin >> num)

C++ cin.ignore()

在说ignore前说一下cin这个I/O输入关键字. cin要求用”回车“来提交数据!!!!!----------这个十分重要! #include<iostream> using namespace std; void main(){ int a; cin.ignore(1,'\n'); cin>>a; cout<<a<<endl; int b; cin.ignore(2,'\n'); cin>>b; cout<<b<<e

c++中cin的基本用法

一.最基本的用法cin>> 接收一个数字.字符.字符串,遇"空格"."TAB"."回车"都结束 例如: <span style="font-size:18px;"><span style="font-size:18px;">#include <iostream> using namespace std; main () { int a,b; cin>&g

【PAT甲级】1077 Kuchiguse (20 分)(cin.ignore()吃掉输入n以后的回车接着用getine(cin,s[i])输入N行字符串)

题意: 输入一个正整数N(<=100),接着输入N行字符串.输出N行字符串的最长公共后缀,否则输出nai. 代码: #include<bits/stdc++.h>using namespace std;string s[107];int length[107];char ans[307];int main(){ ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); int n; cin>>n; cin.igno

svn ignore 的用法(忽略文件及目录)

svn ignore 的用法(忽略文件及目录) 若想创建了一个文件夹,并且把它加入版本控制,但忽略文件夹中的所有文件的内容: $ svn mkdir spool $ svn propset svn:ignore '*' spool $ svn ci -m 'Adding "spool" and ignoring its contents.' 若想创建一个文件夹,但不加入版本控制,即忽略这个文件夹: $ mkdir spool $ svn propset svn:ignore 'spoo

cin.get ()的用法:

有三种调用方式, char str[ArSize]; char ch; 1.cin.get();//没有参数 2.cin.get(ch);//有一个参数 3.cin.get(str,ArSize)://有两个参数 另外还有一个新增的, 4.cin.getline(str,ArSize); 假设输入流里有这样一长字符串:"qwertyuiop\n","\n"表示键盘输入以后按了回车键. 调用cin.get(),就会读取输入流里的一个字符,包括换行符,每调用一次就会读取

关于while 中ignore 的用法

[[email protected]~]#echo "1 2 3 4 5" |while read ignore args;do echo $args ;done 2 3 4 5 6 在这里,第一个"1"被忽略,直接从第二个开始输出. 而且,这里可以连续使用多个ignore来实现忽略. [[email protected] ~]# echo "1 2 3 4 5 6" |while read ignore ignore args; do echo