【整理】【C++基础】 cin输入

Input and Type

input输入操作符>>对类型敏感,也就是说它根据待输入的变量的类型来输入。比如

int main
{
    string name; int age;
    cin>>name;
    cin>>age;
}

如果,键入Kathy 18>>操作符会将Kathy读入name,18读入age。为什么不会将整个输入Kathy 18读入name呢?这是因为对字符串的读取终止于空格,比如单个空格、换行或者Tab字符。此外,空格会被>>忽略掉,如果你在一个输入的数字之前键入很多空格,>>会忽略那些空格只读入数字。

如果不按照类型来输入会怎么样呢?比如我们键入18 Kathy,18会被作为一连串的字符读入name,此外,由于Kathy不是整数,将不会被读取到,age的值是一个无意义的随机数(程序执行时age所在的内存单元存储的值),这是因为,我们没有对age进行初始化赋值,也没有成功地给age读取一个值。对于由于输入格式导致的失败更详细的介绍在下一节。

修改上述程序

int main()
{
    string name; int age;
    cin >> name >> age;
    cout << "Hello, " << name <<"(age:" << age << ")" << endl;
}

注意,我们可以在一条输入命令中输入多个变量的值,同样,我们也可以在一条输出命令中输出多个变量的值。

一个string>>读取输入数据是默认把空格作为终止标志,也就是说只能读入单个单词。但是如果我们想要读入多个单词怎么办呢?比如我们想要读入完整的姓名比如Kathy Chen,最简单的方法就是使用两次>>,比如

    string first_name, last_name;
    cin >> first_name >> last_name;

此外要注意,对于数值类型,在输入时,我们可以输入表达式,比如

    int age;
    cin >> age;

输入5*2,age的值会读入为10。

Input Format Errors

>>是对变量类型敏感的,如果我们键入的类型错误的数据,比如对于待输入的整型变量,键入了字符串,就会发生错误,不能继续输入。

int main()
{
    string name; int num1, num2;
    cin >> name >> num1;
    cout << "Name:" << name << "Num1:" << num1 << endl;
    cin >> num2;
    cout << "Num2:" << num2 <<endl;
}

如果输入test wrtype,会发现num2无法输入了。因此,num1是int类型的,而wrtype是一个字符串,因此cin进入了错误状态。

在《C++ Primer Plus》的第六版第六章介绍了cin输入流的机制:
当遇到无效字符或遇到文件结束符(不是换行符,是文件中的数据已读完)时,输入流cin就处于出错状态,即无法正常提取数据。此时,对cin流的所有提取操作将终止。在 IBM PC及其兼容机中,以Ctrl + Z表示文件结束符。在UNIX和Macintosh系统中,以 Ctrl + D表示文件结束符。当输入流cin处于出错状态时,如果测试cin的值,可以发现它的值为false(假),即cin为0值。如果输入流在正常状态,cin的值为true(真),即cin为 一个非0值。可以通过测试cin的值,判断流对象是否处于正常状态和提取操作是否成功。如:

if(!cin.good()) //if表达式判断为真时cin输入流处于出错状态,无法正常提取数据
    cout<<"error";

cin状态

1. cin状态有如下几种

常量含义failbit标记位的值eofbit标记位的值badbit标记位的值转化为10进制
ios::failbit输入(输出)流出现非致命错误,可挽回1004
ios::badbit输入(输出)流出现致命错误,不可挽回0012
ios::eofbit已经到达文件尾0101
ios::goodbit流状态完全正常0000

分别对应cin.fail(), cin.bad(), cin.eof(), cin.good()

2. 了解几种cin状态有关的函数

C++将输入看作是流入程序的字符流,iostream文件定义cin为这种流的对象。对应的输入都会先存入输入缓冲区,cin从输入缓冲区中读入数据,所以当缓冲区中有数据残留时,cin直接取得残留数据而不会请求键盘输入。cin是以空格(单个空格,多个空格,tab,回车)分隔的,空格不进入缓冲区。

  1. cin.clear() 清除cin的错误状态
    cin.clear()用处在于如果输入发生错误,那么流状态被标记为错误,你必须清除这些错误状态,以使你的程序能正确适当地继续运行。

  2. cin.ignore(int n, char c)
    cin.ignore(5, ‘c’)是从数据流(cin)中提取字符,提取的字符被忽略(ignore),不被使用。每抛弃一个字符,它都要技术和比较字符,如果计数值达到5或者被抛弃的字符是’c’,则函数指定终止,否则它继续等待输入。如果你用ignore(4)而缓冲区中只有三个字符,那么接下来的输入的那个也要被ignore。==它的一个常用功能就是用来清除以回车结束的输入缓冲区的内容,消除上一次输入对下一次输入的影响。

    // 把回车之前(上一次输入)的字符从输入缓冲区中清除出去
    std::cin.clear() ; // to be safe, clear error flags which may be set
    std::cin.ignore(std::numeric_limits<int>::max(), '\n');
    
  3. cin.sync 输出与输入同步,如果这时候缓区不空就打印出来。sync时输入输出都清空,输入是丢掉,输出是打印出来。网上很多说法是用于清空输入缓冲区,但这个东西的原意是同步输入流,由于各个编译器对同步功能的实现不同,很可能无法清空缓冲区,因此,建议使用cin.ignore来完成清空缓冲区的操作。
    Does cin.sync() always work?
    关于cin.sync()的解释

3. 对于cin标准输入流检测到用户输入错误内容时,一般清空下应当采取以下三个步骤一一进行:

  1. 重置cin以接受新的输入
  2. 删除错误输入
  3. 提示用户再输入

第一步重置cin以接受新的输入是要最先做的,一般用成员函数clear();形式为cin.clear();如果省略这条语句,程序将拒绝继续读取输入。cin.clear()是用来更改cin的状态标示符的。通俗的讲就是将一个出错的“流”恢复为“好”,并设置goodbit状态位。

示例:

int main()
{
    int num; int num2;
	if (!(cin >> num >> num2))
	{
		cerr << "input error! please input again!" << endl;
		cin.clear();
		int len = numeric_limits<int>::max();
		cin.ignore(len , '\n');
		auto a = cin.good();
	}
    return 0;
}

参考

  1. <<C++ priciples and practice using c++>>
  2. C++ 的cin输入注意【转】----cin的状态
  3. cin标准输入流的错误处理
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页