刷题中输入处理c++篇


感觉每次公司做题都会在输入处理中花费太多的时间,有时候甚至写不出来,现在好好总结一下,主要用c++的cin来处

cin

cin是C++编程语言中的标准输入流对象,也就是要进行I/O操作,所以的I/O操作均是内核态管理的,操作系统对应所以的标准I/O均有缓冲区的概念,数据先存在缓冲区中,后面再通过系统调用传入用户空间,即istream类的对象。cin主要用于从标准输入读取数据,这里的标准输入,指的是终端的键盘。此外,cout是流的对象,即ostream类的对象,cerr是标准错误输出流的对象,也是ostream 类的对象。这里的标准输出指的是终端键盘,标准错误输出指的是终端的屏幕。
在理解cin功能时,先输入输入缓冲区。当我们从键盘输入字符串的时候需要敲一下回车键才能够将cin才能读入缓冲区的内容,回车键(\r)会被转换为一个换行符\n,这个换行符\n也会被存储在cin的缓冲区中并且被当成一个字符来计算!比如我们在键盘上敲下了123456这个字符串,然后敲一下回车键(\r)将这个字符串送入了缓冲区中,那么此时缓冲区中的字节个数是7 ,而不是6。
但是cin>>提取的时候是以回车或者空格作为结束的,一个>>一个结束符(或者连续的数个结束符)–参考这个链接(https://blog.csdn.net/dangwei_90/article/details/8871852?ops_request_misc=&request_id=&biz_id=102&utm_term=cin%E9%81%87%E5%88%B0%E7%A9%BA%E6%A0%BC%E5%92%8C%E5%9B%9E%E8%BD%A6&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-0-8871852)
cin读取数据也是从缓冲区中获取数据,缓冲区为空时,cin的成员函数会阻塞等待数据的到来,一旦缓冲区中有数据,输入结束(enter),就触发cin的成员函数去读取数据。当cin>>从缓冲区中读取数据时,若缓冲区中第一个字符是空格、tab或换行这些分隔符时,cin>>会将其忽略并清除,继续读取下一个字符,若缓冲区为空,则继续等待。但是如果读取成功,字符后面的分隔符是残留在缓冲区的,cin>>不做处理,可以用cin.get()或getchar()清除缓冲区的最后一个回车。
使用一个istream的对象作为条件时,效果是检查流的状态。若流有效,则检测成功,返回true。当遇到文件结束符或者无效的输入(比如用一个字符来作为一个整型数的输入时),istream的对象状态会变为无效。
总而言之:
(1) 输入数据时需要敲回车键才能将数据送到缓存器,cin才能读取缓存区的数据。
(2) 当cin遇到文件结束符(windows中为:ctrl +Z , Unix 中为:ctrl +D),或无效输入才能使cin状态无效。

注意:以下包含多个案例和单个案例两种类型,但是很多时候刷题只用单个案例类型就行,应该是后台会多次调用该函数;也可以用多个案例的模式,如果输入实例中有明确的多个案例那么必须是多个案例了。

getline

c++输入字符串到string类可以用getline函数,第一个参数是cin,第二个参数是string类的变量,第三个参数是结束标志(默认为回车)。
该函数不会读入结束标志,而是跳过。
当cin>>从缓冲区中读取数据时,若缓冲区中第一个字符是空格、tab或换行这些分隔符时,cin>>会将其忽略并清除缓冲区,继续读取下一个字符,若缓冲区为空,则继续等待。但是如果读取成功,字符后面的分隔符是残留在缓冲区的,cin>>不做处理(最后残留了回车)。

对于getline函数,在函数遇到和结束定界符相等的字符时函数结束,同时函数抽出定界符,此种情况下该定界符既不被放回输入流,也不被放入要生成的字符串。所以由此可以理解输入结束后的第一个回车是定界符,被确认后抛弃,而第二个才是程序执行运行时正常需要的!

所以这是getline和cin的区别,cin遇到空白键,tab键,换行符终止,可是这个符号还留在缓冲区中。
而getline遇到终止符号停止输入,该符号也请离缓冲区。
所以假如你按十次回车,那么getline函数输入到十个string变量中,当然每次回车表示一次结束,所以是个string变量都会是空串。cin则不同,他会一次又一次的忽略回车键,并丢掉,直到等到一个正经的字符串的输入

getline(cin,s)

因为回车输入的是一个换行符,相当于另起一行,所以getline()会把这个空行读到s里面去,你最后输出的当然就是一个空行。
但是,要理解这个过程究竟是怎么发生的,题主应该要明白几个概念:
(1)eof标志
(2)cin的状态
while(geline(cin,s))这个语句的执行过程是这样的:
先调用getline()函数,getline()将istream cin中的内容读取一行(你输入的是hello world),保存进string s中,而getline()的返回值就是cin
也就是说,这个循环的判定条件是while(cin),cin是怎么转化为bool类型进行条件判断的呢?

总结

对于while(cin>>x)和while(getline(cin,x))的区别和联系可以简单的这样认为:
(1)二者遇到换行符’\n’就会进入循环体工作,但是while(cin>>x)再缓冲区残存了’\n’,后续不会对cin>>x的操作造成影响,但是会对getline(cin,x)造成影响,如果没有清楚这’\n’就直接调用getline(cin,x),x中就是一个空字符串
(2)对于前者使用了cin,后面要使用getline(cin,x),要使用一个cin.get(),将最后的’\n’清除。

简单输入

#include<iostream>
using namespace std;
int main()
{
	int n = 0;
	cin>>n;
	cout << n <<endl;
}

//多个案例
int main()
{
	int n = 0;
	while(cin>>n)
	{		 //当cin遇到文件结束符(windows中为:
			//ctrl +Z , Unix 中为:ctrl +D),或无效输入才能使cin
			//状态无效。
	cin>>n;
	cout << n <<endl;}
}

输入两行–第一行为n,第二行为n个数字

#include<iostream>
using namespace std;
int main()
{
	int n = 0;
	vector<int> num;
	cin>>n;			//单个案例
	for(int i=0;i<n;i++)
	{
		int temp;
		cin>>temp;
		num.push_back(temp);
	}
	//下面是其他操作
	cout << n <<endl;
}
//多个案例
int main()
{
	int n = 0;
	vector<int> num;
	while(cin>>n)//多个案例--所有的操作都要在里面--不能return
	{
		for(int i=0;i<n;i++)
		{
			int temp;
			cin>>temp;
			num.push_back(temp);
		}
		//下面是其他操作
		cout << n <<endl;
	}			
	return 0;
}


输入多行

//输入多行--一行一个数字
int main()
{
	int n = 0;
	
	while(cin>>n)//多个案例--所有的操作都要在里面--不能return
	{
		vector<int> num;
		for(int i=0;i<n;i++)
		{
			int temp;
			cin>>temp;
			num.push_back(temp);
		}
		//下面是其他操作
		cout << n <<endl;
	}			
	return 0;
}

//输入多行--一行多个数字个数字
int main()
{
	int n = 0;
	int m = 0;
	while(cin>>n>>m)//多个案例--所有的操作都要在里面--不能return
	{
		vector<vector<int>> num;
		for(int i=0;i<n;i++)
		{	
			vector<int> tmpList;
			for(int j=0;j<m;j++)
			{
				int temp;
				cin>>temp;
				tmpList.push_back(temp);
			}
			num.push_back(tmpList);	
		}
		//下面是其他操作...
		cout << n <<endl;
	}			
	return 0;
}

输入多行–每行不定

使用getline

//输入多行--一行多个数字个数字
int main()
{
	int n = 0;
	while(cin>>n)//多个案例--所有的操作都要在里面--不能return
	{
		string str;
		vector<vector<int>> num;
		while(getline(cin,str)&&!str.empty())
		{
			
			int start = 0,end = str.size()-1;
			for(int i=0;i<str.size();i++)
			{	
				vector<int> tmpList;
				if(str[i]==' ')
				{
					string strT = str.substr(start,i-start);
					int temp=stoi(strT);
					tmpList.push_back(temp);
				}
			}
			num.push_back(tmpList);	
		}
		
		//下面是其他操作...
		cout << n <<endl;
	}			
	return 0;
}

输入含有空格的字符–getline

int main()
{
	int n = 0;
	while(cin>>n)//多个案例--所有的操作都要在里面--不能return
	{
		vector<string> strList;
		int str;
		while(getline(cin,str)&&!str.empty())
		{
			strList.push_back(str);
			str.clear();
		}
		//下面是其他操作...
		cout << n <<endl;
	}			
	return 0;
}

利用输入流

利用输入流也可以输入不定长的数组,在对iss>>num,只要右边的数据类型是整形,那么输出的就是整形,如果是字符串,就是字符串。

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
 
using namespace std;
 
int getNum(string &str, vector<int> &inputNum)
{
    istringstream iss(str);	//把字符串转为输入流
    int num = 0;
    while(iss >> num) {//用>>提取缓冲的时候可以自动跳过空格,并且自动匹配数据类型
        inputNum.push_back(num);
    }
    str.clear();
    return 0;
}
 
int main()
{
    string inputStr;
    vector<int> inputData;
    while (getline(cin,inputStr)) {
        if(getNum(inputStr,inputData)) {
            return 0;
        }
        for (auto i = inputData.begin(); i != inputData.end(); i++) {
            cout << *i << " ";
        }
        cout << endl;
        inputData.clear();
    }
 
    return 0;
}

持续更新总结。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值