今天同学调试一个简单的程序的时候发现了问题,我们两个讨论的时候弄出了好多乐子

#include <iostream>
using namespace std;
int main()
{
    ;
    cout << "c1=";
    while (cin >> c1)
    {
        if ('y' == c1)
        {
            cout << "Good" << endl;
            break;
        }
        else
            cout << "Try again" << endl;
    }

    system("pause");
}

就是这个程序,其实很简单,同学测试的时候每次都是输入的25这样两个字符的数,导致每次打印两个Try again 而发给我测试的时候我都是用2这种一个字符的数

导致程序在我这里是正常的,到他那里就错了。。。。。其实重点是ci是一个字符类型的对象,而且cin是一个流,把键盘输入陆续输出到c1对象,所以25是字符'2'和'5',记录这个主要是告诉自己以后调试的时候要先用别人的测试用例,这样有助于快速定位到问题

----------------------------------------------------------以下为转载内容-------------------------------------------------------------------------------------------------------------

cin在你输入的时候,会跳过空白字符,它们会被放到缓冲区中,当你用接受空白字符的输入流时,这个时候从缓冲区(缓冲区实际上是队列)中获取到它们的

windows按下回车输入的是'\r' '\n'

int main()  

{  

    ]={};  

    ]={};  

    cin >>buf1;
    cin.getline(buf2,); // 这里似乎不等待输入  

    ;  

}  

解决办法如下:

 int main()
{  

    ]={};  

    ]={};  

    cin >>buf1;
    cin.ignore(); // 或者 cin.sync(); 之类的  

    cin.getline(buf2,);  

    ;  

} 

这是为什么呢?

因为,首先, Windows 上敲一下回车键,实质上是输入两个字符:回车符,紧跟着换行符。这两个字符的 ASCII 码分别为 0x0D 和 0x0A,一般来说,其C++转义表示分别为 '\r' 和 '\n'。然后,cin>> 默认是以一个或多个接连的白空格为间隔,cin.getline 默认则以单个换行符(0x0A)为间隔。回车符和换行符都属于白空格。

为了展示这个看不见的回车键敲击,用 istringstream 举个例子:

void disp(char *buf,int n)
{
    ;i<n;++i)
        printf("0x%02X ",buf[i]);
    printf("\n");
}

int main()
{
    disp();
    // 这相当于在控制台敲回车键,然后敲入s1,然后敲回车键,然后敲入s2
    // 0x0D 0x0A 0x73 0x31 0x0D 0x0A 0x73 0x32 0x00
    printf("\n");

    {
        istringstream iss("\r\ns1\r\ns2");
        ]={};
        ]={};

        iss >>buf1;
        iss >>buf2;

        disp(buf1,); // 0x73 0x31 0x00 0x00 0x00
        disp(buf2,); // 0x73 0x32 0x00 0x00 0x00
    }

    printf("\n");

    {
        istringstream iss("\r\ns1\r\ns2");
        ]={};
        ]={};

        iss.getline(buf1,);
        iss.getline(buf2,);

        disp(buf1,); // 0x0D 0x00 0x00 0x00 0x00
        disp(buf2,); // 0x73 0x31 0x0D 0x00 0x00
    }

    ;
}

用 cin 的道理是一样的。区别在于相关的标准库函数会把 0x0D 转换为 0x0A,这就相当于回车键最终敲入缓冲区的是接连的两个换行符。由于这不影响讨论,下文还是用 0x0D 指代。

cin>> 每读到其所期待的东西后碰到 0x0D,就“断”一下,紧跟着的 0x0A 还在缓冲里。此时,如果改用 cin.getline() ,0x0A 立即被读入,而该间隔符前面没有字符,于是就有了 getline 已完成却没有 get 到 line 的错觉。而如果没有改用 cin.getline(),继续用cin>>,那么 cin>> 碰到紧跟着的 0x0A 时,这是在还没读到其所期待的东西就碰到了白空格,它的反应就是跳过该字符(这正是 cin.ignore(); 要做的),接着继续去读其所期待的东西。

关于cin的更多相关文章

  1. cin.ignore()函数的用法

    cin.ignore(a,ch)方法是从输入流(cin)中提取字符,提取的字符被忽略(ignore),不被使用.每抛弃一个字符,它都要计数和比较字符:如果计数值达到a或者被抛弃的字符是ch,则cin. ...

  2. cin的使用问题

    #cin的使用问题 cin输入类型不匹配的情况: #include<iostream> using namespace std; void main() { int i = 0; whil ...

  3. using namespace std 和 using std::cin

    相较using std::cin使用using namespace std不会使得程序的效率变低,或者稳定性降低,只是这样作会将很多的名字引入程序,使得程序员使用的名字集合变小,容易引起命名冲突. 在 ...

  4. while(cin.eof)出错 poj

    zoj遇到c++如何判定输入流结尾的问题,一不小心就超时了 楼下的代码可以通过zoj #include<iostream> using namespace std; int main(){ ...

  5. cin

    cin 是预定义的标准输入流对象,cin 用来接收字符串时,遇“空格”.“TAP”.“回车”时都会结束.

  6. C++输入cout与输出cin

    输入和输出并不是C++语言中的正式组成成分.C和C++本身都没有为输入和输出提供专门的语句结构.输入输出不是由C++本身定义的,而是在编译系统提供的I/O库中定义的.C++的输出和输入是用" ...

  7. cin, cin.getline等函数

    char s[100]; cin>>s;         // 输入一个字符串,遇“空格”.“TAB”.“回车”都结束 cin.getline(s, 20);    // cin.get( ...

  8. strlen 字符型数组和字符数组 sizeof和strlen的区别 cin.get(input,Arsize)

    strlenstrlen所作的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符'\0'为止,然后返回计数器值 ...

  9. C++IO关于cin>>和getline的理解

    这个问题困扰了我有一段时间了,趁着十一放假有时间,仔细研究了一下 首先来看一下输入输出运算符cin>>的构成:cin和>> cin>>是由两部分构成的,cin和&g ...

  10. 为什么可以用while(cin)?

    为什么可以用while(cin)?   /** * @brief The quick-and-easy status check. * * This allows you to write const ...

随机推荐

  1. swap 内存不足

    参考:https://stackoverflow.com/questions/5682854/why-is-the-linker-terminating-on-me-when-i-build-clan ...

  2. selenium鼠标悬停操作

    有些网页一打开会有一个弹窗,弹窗不消失无法进行取元素操作,只有把鼠标悬停在上面弹窗才会消失,这时就用到了selenium的悬停操作 鼠标悬停  move_to_element() 定位到要悬停的元素 ...

  3. HDU - 1003 Max Sum 【DP】

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1003 题意 给出一个序列 要求找出一个和最大的子序列 思路 O(N)的做法 但是要标记 子序列的头部位 ...

  4. android客户端登录&注册的实现

    MainActivity多线程的实现: package com.example.loginconnect; import java.lang.ref.WeakReference; import jav ...

  5. 通过设置PHPSESSID保存到cookie实现免登录

    $cookieParams = session_get_cookie_params(); session_set_cookie_params( 3600,// 设置sessionID在cookie中保 ...

  6. P3506 [POI2010]MOT-Monotonicity 2

    题目 P3506 [POI2010]MOT-Monotonicity 2 第一次切掉没题解的题\(qwq\) 做法 首先确定\(a_i\)的位置后显然就能确定\(a_{i+1}\)的位置,建一棵权值线 ...

  7. 光流法跟踪fast角点思路

    光流法需要include<opencv2/video/tracking.hpp>,用到列表,所以要include<list><vector>1.读取文件定义图像存储 ...

  8. mysql学习笔记1

  9. Java -- AWT 画图,图像处理

    1. AWT画图  Graphics类  提供绘制简单图形的方法 更新图片时用到 repaint , update , 程序不应该主动调用paint和update, 这两个方法都应该是由AWT系统负责 ...

  10. 大话设计模式--外观模式 Facade -- C++实现实例

    1.  外观模式: 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这个子系统更加容易使用. 外观模式的使用场合: A: 设计初期阶段,应该要有意识的将不同的两个层分离. ...