c++中的输入输出都是用“类”来进行,无论是 cin,和cout都是类的一个对象。 c++中负责IO的有3中类型 1: istream、ostream 从流读写数据(i表示in也就是读,o表示out也就是写),你可以认为流就是控制台输入输出的数据,cin和cout就分别是他们俩的对象。 2: ifstream、ofstream f 表示file,也就是从文件读写数据 3: istringstream, ostringstream 从string读写数据。
其中2,3是继承的1。那么有了这些类之后读写过程是怎样的呢? ?我们以cin为例,首先你在控制台输入字符敲下回车键以后数据就到了到缓冲区,你可以认为cin与缓冲区之间已经建立好了一层通道可以直接读数据,所以我们直接用cin读数据就可以了是不是很简单。 ? 那如何从文件读写数据?和cin一样,我们创建一个文件流对象,然后需要我们自己用open函数建立通道,然后就可以通过对象进行写读数据操作。第三种string也是一样的。
#include <iostream>
#include "my_lib.h"
using namespace std;
int main(){
string s;
cin >>s;
cout <<s;
ifstream ifs;
ofstream ofs;
ifs.open("./a.txt");
ofs.open("./b.txt");
ifs >> s;
ofs << s;
}
分析上面的代码我们发现无论是ifs还是cin都只读取了一串字符,遇到空格就不读取了,而且一开始的自动忽略了,那剩下的内容呢?读写规则是怎样的,还有如果想读取一行又该如何解决?
cin cout 具体读写规则 首先cin是从标准输入(缓冲区)读数据的。当开始读数据时,如果一开始遇到的是分隔符比如tab 换行,空格等,它会自动忽略这些字符接着读,如果读入数据之后再遇到分隔符则本次读入结束(进入下一行代码),注意此时分隔符仍留在缓冲区未清理。举个栗子
#include <iostream>
#include "my_lib.h"
using namespace std;
int main(){
string s1,s2;
int a1,a2;
cin >> s1;
cin >> a1;
cin >> s2;
cin >> a2;
}
一定要弄懂对分隔符的处理方式,这很重要!! cin.get()函数 cin 是istream类的一个对象,所以他有类成员函数也并不奇怪,常用的cin.get()方式如下
int get();
istream& get(char& var);
istream& get( char* s, streamsize n );
istream& get( char* s, streamsize n, char delim);
先看前两个,读取一个字符, 需要注意的是,和cin不一样,如果一开始有分隔符这种操作是会读取分隔符然后结束的,举个栗子。
#include <iostream>
#include "my_lib.h"
using namespace std;
int main(){
char c;
char d;
cin.get(c);
cin.get(d);
}
再看第三个读取字符串操作,注意,这里参数为char* 不能为string。s是你要输入的char数组的地址,streamsize是扫描的字符数 get函数会从缓冲区第一个字符开始扫描直到遇到’\n’换行符,或者扫描的字符大于等于streamsize了(也就是最多扫描streamsize-1个),然后将扫描的字符串加上’\0’送入数组(没错,最后会自动给他加一个结束符标识结束)。举个栗子
#include <iostream>
#include "my_lib.h"
using namespace std;
int main(){
char s[7] = "hellh";
cin.get(s,5);
char c;
cin.get(c);
}
第四个get()函数把换行符变为了特殊的字符,遇到换行符不再结束,而是遇到该字符结束,不再细讲。 需要注意的是,如果一开始就是一个回车,这时候最好不要用第三四种读入(没什么意义),而且好像之后cin就不起作用了。 cin.getline()函数
istream& getline(char* s, streamsize count);
istream& getline(char* s, streamsize count, char delim);
cin.getline()和第三四种cin.get不同的是,遇到换行符会结束,并清空缓冲区中的换行符 但如果一开始就是一个回车,这种方法不会出错,他会将一个’\0’写入到s中,然后清空这个回车。 getline()函数 cin.get()或者cin.getline()向char*中输入毕竟不太方便,所以c++定义了一个全局函数getline(),可以直接向string中输入.
istream& getline (istream& is, string& str);
istream& getline (istream& is, string& str, char delim);
这个没啥好说的,遇到换行符或者你自定义的delim结束,会自动加上一个’\0’写入string, 然后把换行符清空。 但如果一开始就是一个回车,这种方法不会出错,他会将一个’\0’写入到s中,然后清空这个回车。 因为可以向string输入用法也简单,所以一般都是用这种吧,而且这种还可以和stringstream搭配(刷题必备)。 istringstream ostringtream 和上面的两种一样,只不过是绑定到string上。
#include <iostream>
#include "my_lib.h"
using namespace std;
int main(){
string s1="ffrewe";
string s2;
istringstream ssin(s1);
ostringstream ssout;
ssout << "fefre fr";
s2 = ssout.str();
cout << s2;
}
总结 1、首先要搞清楚各个函数是如何处理分隔符的!! 2、比如刷题的时候,如果告诉你数据的行数n, 每行数据量m,那就直接建一个vectorvector> 然后用for(int i;…) cin>> 就可以了。
#include <iostream>
#include "my_lib.h"
using namespace std;
int main(){
int n;
int m;
cin >>n>>m;
vector<vector<int>> v(n,vector<int>(m));
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin >> v[i][j];
}
}
}
3、如果只告诉你数据的行数,但不告诉你每行数据有多少呢?
#include <iostream>
#include "my_lib.h"
using namespace std;
int main(){
int n ;
cin>> n;
getchar();
vector<vector<int>> v(n);
for(int i=0;i<n;i++){
string temp;
getline(cin, temp);
istringstream ssin(temp);
int a;
while(ssin >> a){
v[i].emplace_back(a);
}
}
printMatrix(v);
}
需要注意之所以可以用while(ssin>>a)是因为把temp转化为ssin的过程中,它自动在temp的后面加了一个结束符,当ssin遇到结束符时会返回一个非1的值,此时while结束了。你直接用while(cin >> a)读取控制台的内容,那永远不会结束,因为cin >> 遇到换行符会自动过滤掉但并不会结束,就一直阻塞在那了!!所以我们一般看不到也不知道行数也不知道个数的控制台输入,那时候可能要判断缓冲区还有没有数据。。以后在写吧 还有就是各种出错码改状态之类的,有空再写吧。 全文完。。。。如果有用点个赞吧。
|