C++ I/O

C++中的I/O

遗忘点

对于各个in,out对象,凡是>> 操作,只要是读不到东西,都是返回0.
而且都是遇到空格就停止了。

I/O操作,是针对内存而言。
是对内存中的数据进行input和output。
这将是之后和文件I/O很多人分不清read,write等等到底是读还是写迷茫之处的根源。

示例:

cin:console in的意思。首先确定是个in,相对谁?所有I/O都是相对内存的。所以是in到内存中去,来自哪?cin的c告诉你了呀,是console。

其实,所有的ostream对象,都是把数据从内存中拿出来,输出去。
针对文件的ostream不就是把内存中的数据从内存中拿出来output到文件中吗
针对console的ostream(cout)不就是把内存中的数据放到screen上吗
针对字符串buffer的ostream不就是把内存中的数据放入一个buffer中吗。
istream同理。是那些来源in到内存中去。
根据对象属于istream还是ostream来判断是读入还是输出。(相对M)

控制台I/O

  1. 可以参考C语言的文件相关函数。这里是C++,不会再赘述,只会罗列。
    常用的freopen()一般改成对文件的io非常方便。(竞赛+非工程)

  2. 重载>> <<对对象可以实现I/O

  3. 其他的罗列如下:

fopen

in:
cin

setw(输入字符的最大个数)

getchar
gets
scanf (正则)
sscanf
对文件:
fgetc
fgets
fscanf
fread

out:
cout

setprecision(浮点数小数点后数字个数(ios::scientific/ios:fixed)/有效数字个数(自动/默认方式))
setiosflags(ios::scientific/ios:fixed/default) 设置输出格式
resetiosflags(ios::scientific/ios:fixed/default) 取消设置输出格式
cout<<string/char * 输出字符串
cout<<(void *) string/char * 输出指针的内容(地址)
cout<<*char * 输出str[0]

clog
cerr
putchar
puts
printf
sprintf
对文件:
fputc
fputs
fprintf
fwrite(二进制)

feof 常用while(!feof(fp)){…}
fclose
fflush 清空缓冲区 凡是和flush相关的都是清空缓冲区或者立即输出不过缓冲区的。
随机访问:
fseek
ftell

文件I/O

这里是上课老师主要讲的C++part的对文件的I/O对象
ios派生出
istream(控制台输入)和ostream(控制台输出)
前者派生出

  • ifstream 文件输入
  • istrstream 字符串输入
    后者派生出
  • ofstream 文件输出
  • ostrstream 字符串输出
    而iostream这个子类时由istream和ostream多继承而来,实现了存和取
    它派生了两个重要子类
  • fstream 可以对file存和取
  • strstream 可以对字符串变量存和取

ostream对象常用的成员函数

ostream & ostream::put(char ch);   //单个字符
ostream & ostream::write(const char *p,int count);  //输出p指向空间中count个字节

istream对象常用的成员函数

istream & istream::get(char &ch);   //单输入一个字符到内存中名为ch的变量空间中
istream & istream::read(const char *p,int count);  //读入count个字节到p指向的M中
istream & istream::getline(char *p,int count,char delim='\n'); //向一个字符串p处直到输入了count-1个字符  或者就是遇到了\n结束读入到p中  
//getline如果没有读到字符会返回false可判断文件是否结束

char str[10];
cin.getline(str,10);//从键盘输入9个字符  可以包含空格,直到遇到第十个字符(补\0)或遇到\n

判断操作是否成功:

bool ios::fail();
//尤其是对文件指针移动的时候很容易飘逸越界等等,需要用fail函数判断
注意重载<< >>来输出A类的私有成员时,必须在A类中声明对operator << >>的重载是友元。而且重载的返回值必须是引用类型,否则无法实现连续输出。而且父类的这个重载,对于子类像一些文件fstream都是可以接着用的。肥肠的方便。

cout,cin返回的都是xstream对象。
cout<<A<<B;这种,如果对C类对象A,B重载,如果返回仅仅是ostream而不是ostream & 在先输出A之后,就无法再输出B。因为返回的那个ostream(重载的)对象调用后就消失了,传引用就是保证是对这个对象真真切切本身做了修改,而不是它的拷贝构造。
总之,连续操作必须返回值传递引用
如果要用间接访问,动态绑定。需要对父类响应重载的<<,>>函数声明成虚函数即可。

i/ostream对象的具体使用

ostream myout("data.dat",ios::out|ios::binary); //如此和文件建立关联
if (!myout) exit(-1) ; //说明没有成功创建这个和data.txt关联起来的文件输出对象
myout.write((char*) &student,sizeof(student));//char *转化为字节。对一个struct 为student类型的结构体一次向文件中out一个学生信息元素。而且是二进制形式。  
myout.close();
int ,x,y;
ifstream myin("data.txt",ios::in);//从文件读数据in到M
if (!myin) exit(-1);
myin>>x>>y;
or
int ,x,y;
ifstream myin("data.dat",ios::in|ios::binary);//从文件读数据in到M
if (!myin) exit(-1);
myin.read((char*)&x,sizeof(x));
//以二进制的方式读入数据到内存中
if (myin.eof()!=0) myin.close();//说明已经读入结束,可以关闭文件了

int ios::eof()
判断文件是否已经读入结束
返回非0(true)就是已经读入结束。

随机存取

fstream类,随机性需要对指针进行调度

fstream casual_io("data.dat",ios::in|ios::out);
既支持in也支持out
随机性:
istream & istream::seekg(绝对位置);
istream & istream::seekg(offset,相对位置);
streampos istream::tellg();//获得指针位置

ostream & ostream::seekp(绝对位置);
ostream & ostream::seekp(offset,相对位置);
streampos ostream::tellp();//获得指针位置

相对位置:

  • ios::beg 开头
  • ios::cur 当前位置
  • ios::end 文件末尾

一些实例(其实是老师布置的天杀的作业)(过几天写完了上传)

  1. 编写一个拷贝程序,它能把一个文件中的内容赋值到另一个文件中
#include<bits/stdc++.h>
using namespace std;

int main() {
   ifstream myin("data1.txt",ios::in);
   
   ofstream myout("data2.txt",ios::out);
   char filecontent[500];
   
   while(!myin.eof()) {
   	myin.getline(filecontent,1000);
   	myout<<filecontent;//一次读入一个不含空白符的内容 	
   }	
   cout<<"拷贝结束\n";
   return 0;
}
  1. 编写一个程序,统计一个文本文件的行数
#include<bits/stdc++.h>
using namespace std;
const int MAX_LINE = 1000 ;
int main() {
	const char *filename = "enfile.txt";
	ifstream myin(filename,ios::in);
	int line=0;
	char s[MAX_LINE];
	while(myin.getline(s,MAX_LINE)!=false){
		line++;
	}
	cout<<filename<<"共有"<<line<<"行\n"; 
	
	
    return 0;
}
  1. 编写一个通讯录的IO程序,该程序从键盘输入通讯录,然后把它保存到文件中,通讯录的内容包括:序号,姓名,单位,电话。要求程序中,通讯录是一个类,通过重载<< >>来实现对通讯录的输入和输出.
#include<bits/stdc++.h>
using namespace std;
/*
通讯录的内容包括:序号,姓名,单位,电话。要求程序中,通讯录是一个类
cin
myout到file 
*/ 
class AddressBook{
	private:
		string seq;
		string name;
		string company;
		string tel;
		bool init;
	public:
		bool getinit(){
			return init;
		}
		AddressBook():init(false){
		}
		friend istream& operator >> (istream& in,AddressBook &ab);  //输入符 
		friend ostream& operator << (ostream& out,AddressBook &ab); 	//输出符
		 
}; 
ostream& operator << (ostream& out,AddressBook &ab){
	out<<"序号为"<<ab.seq<<"名为"<<ab.name<<"的公司是"<<ab.company<<",电话是:"<<ab.tel<<endl;
	return out; 
}
istream& operator >> (istream& in,AddressBook &ab){
	cout<<"请输入序列号(停止输入则输入-1):\n";in>>ab.seq;
	if (ab.seq=="-1"){
		ab.init = false;

		return in;
	}
	cout<<"请输入姓名:\n";in>>ab.name;
	cout<<"请输入公司名称:\n";in>>ab.company;
	cout<<"请输入电话号码:\n";in>>ab.tel;
	ab.init = true;
	cout<<"输入完成\n";
	return in;
} 
int main() {
	AddressBook msg;
	ofstream myout("addressbook.txt",ios::app);
	cin>>msg;//此时msg中的init就是true,可以一直输入 

	while(msg.getinit()){
		myout<<msg;
		cin>>msg;
	}
	cout<<"已经全部输入到文件\n";
    return 0;
}

  1. 用文本文件保存该例下的学生信息

实例如下:

#include<bits/stdc++.h>
using namespace std;
enum Sex { MALE, FEMALE };
struct Date {
	int year;
	int month;
	int day;
};
enum Major {
	MATHEMATICS,PHYSICS,CHEMISTRY,COMPUTER,GEOGRAPHY,
	ASTRONOMY,ENGLISH,CHINESE,PHILOSOPHY
};
struct Student
{
	char id[11];
	char name[9];
	Sex sex;
	Date birth_date;
	char birth_place[40];
	Major major;
};

int main() {
	FILE* fp = fopen("student.dat", "wb");
	if (fp == NULL) {
		cout << "打开文件失败\n";
		exit(-1);
	}
	Student st;
	cout << "请输入学号,姓名,性别,出身日期(年,月,日),出生地和专业(以学号为'E'结束):\n";
	scanf("%10s", st.id);
	while (st.id[0] != 'E') {
		//读入个信息到st中
		cin >> st.name;
		cin >> st.sex;
		cin >> st.birth_date.year >> st.birth_date.month >> st.birth_date.day >> st.birth_place;
		cin>> st.major;
		fwrite(&st, sizeof(st), 1, fp);  //将st的值输出到文件(二进制形式)
		scanf("%10s", st.id);
	}
	fclose(fp);
	return 0;

}

如下:

#include<bits/stdc++.h>
using namespace std;
enum Sex { MALE, FEMALE };
struct Date {
	int year;
	int month;
	int day;
};
enum Major {
	MATHEMATICS,PHYSICS,CHEMISTRY,COMPUTER,GEOGRAPHY,
	ASTRONOMY,ENGLISH,CHINESE,PHILOSOPHY
};
struct Student
{
	char id[11];
	char name[9];
	Sex sex;
	Date birth_date;
	char birth_place[40];
	Major major;
};

int main() {
	FILE* fp = fopen("student.txt", "w+");
	if (fp == NULL) {
		cout << "打开文件失败\n";
		exit(-1);
	}
	Student st;
	cout << "请输入学号(以学号为'E'结束):\n";
	scanf("%10s", st.id);
	
	while (st.id[0] != 'E') {
		//读入个信息到st中
		fprintf(fp,"%10s",st.id);
		cout<<"name:";
		cin >> st.name;
		fprintf(fp,"%s",st.name);
		int gender;
		cout<<"性别(0男1女):";
		scanf("%d",&gender);
		if (gender==0){
			fprintf(fp," 性别:男");
		}
		else if (gender==1){
			fprintf(fp," 性别:女");
		}
		else{
			printf("不男不女,默认不是人类\n");
			exit(-1);
		}
		
		
		st.sex = (Sex)gender;//枚举的输入 
		cout<<"出生年";
		cin >> st.birth_date.year ;
		cout<<"月";
		cin>> st.birth_date.month ;
		cout<<"日" ;
		cin>> st.birth_date.day;
		cout<<"出生地点:";
		cin >> st.birth_place;
	fprintf(fp," 出生于%d年%d月%d日,%s",st.birth_date.year, st.birth_date.month, st.birth_date.day , st.birth_place);
	int mj;
		cout<<"专业(输入0~8数字):";
		scanf("%d",&mj);
		if (mj==0){
		fprintf(fp,"MATHEMATICS");
		}
		else if (mj==1){
				fprintf(fp,"PHYSICS");
		}
		else if (mj==2)
			fprintf(fp,"CHEMISTRY");
		else if (mj==3)	fprintf(fp,"COMPUTER");
		else if (mj==4)	fprintf(fp,"GEOGRAPHY");
		else if (mj==5)	fprintf(fp,"ASTRONOMY");
		else if (mj==6)	fprintf(fp,"ENGLISH");
		else if (mj==7)	fprintf(fp,"CHINESE");
		else if (mj==8)	fprintf(fp,"PHILOSOPHY");
		else fprintf("没有标准输入,属于被退学的孤儿");
		
		st.major = (Major)mj;
	fprintf(fp,"\n");
		cout<<"学号:";
		scanf("%10s", st.id);
	}

	fclose(fp);
	return 0;

}

  1. 从键盘读入一堆图形信息(我还以为是OpenGL的,吓死我了)
#include<bits/stdc++.h>
using namespace std;
//定义三个图形
class line {
		double beginx;
		double endx;
		double beginy;
		double endy;
	public:
		double length() {
			return sqrt((beginx-endx)*(beginx-endx)+(beginy-endy)*(beginy-endy));
		}
		friend ostream &operator << (ostream &out,line& l);
		friend istream &operator >> (istream &in,line& l);
};
 ostream &operator << (ostream &out,line &l) {
	out<<"begin corordinate:("<<l.beginx<<","<<l.beginy<<"),"<<"end corordinate:("<<l.endx<<","<<l.endy<<") "<<"length:"<<l.length()<<endl;
	return out;
}
 istream &operator >> (istream &in,line &l) {
		cout<<"请依次输入线的始末坐标(先x,后y)\n" ;
	//先输入第一个坐标的x,y  再第二个 
	in>>l.beginx>>l.beginy>>l.endx>>l.endy; 
}
class Round{
	double x,y;
	double r;
	public:
		friend ostream &operator << (ostream &out,Round &l);
		friend istream &operator >> (istream &in,Round &l);
};
ostream &operator << (ostream &out,Round &l){
	out<<"center corordinate:("<<l.x<<","<<l.y<<"),"<<"radius:"<<l.r<<endl;
	return out;
}
istream &operator >> (istream &in,Round &l){
			cout<<"请依次输入圆的圆心坐标(先x,后y)再输入半径\n" ;
	in>>l.x>>l.y>>l.r;//依次输入圆心坐标和半径
	return in; 
}
class rectangle{
	double x1,y1;
	double length,width;
	public:
	 	friend ostream &operator << (ostream &out,rectangle &l);
		friend istream &operator >> (istream &in,rectangle &l);
}	;
 ostream &operator << (ostream &out,rectangle &l){
	out<<"first corordinate:("<<l.x1<<","<<l.y1<<"),"<<"length:"<<l.length<<"  width:"<<l.width<<endl;
	return out;
}
 istream &operator >> (istream &in,rectangle &l){
	cout<<"请依次输入长方形的一个坐标(先x,后y)再输入长度和宽度\n" ;
in>>l.x1>>l.y1>>l.length>>l.width;
}
int main() {
	line l1;
	Round r1;
	rectangle re1;
	cin>>l1>>r1>>re1;
//	cout<<l1<<r1<<re1<<endl;
//	ifstream filein("GraphicInfo.txt",ios::in) ;
	ofstream fileout("GraphicInfo.txt",ios::out);
//	filein>>l1>>r1>>re1;
	fileout<<l1<<r1<<re1;
	
	return 0;
}
  1. 从上一题保存的图形文件中读入图形信息,并以某种方式把他们输出到显示器
#include<bits/stdc++.h>
using namespace std;
#define MAX_LINE 1000
//定义三个图形
class line {
		double beginx;
		double endx;
		double beginy;
		double endy;
	public:
		double length() {
			return sqrt((beginx-endx)*(beginx-endx)+(beginy-endy)*(beginy-endy));
		}
		friend ostream &operator << (ostream &out,line& l);
		friend istream &operator >> (istream &in,line& l);
};
 ostream &operator << (ostream &out,line &l) {
	out<<"LINE:begin corordinate:("<<l.beginx<<","<<l.beginy<<"),"<<"end corordinate:("<<l.endx<<","<<l.endy<<") "<<"length:"<<l.length()<<endl;
	return out;
}
 istream &operator >> (istream &in,line &l) {
		cout<<"请依次输入线的始末坐标(先x,后y)\n" ;
	in>>l.beginx>>l.beginy>>l.endx>>l.endy; 
}
class Round{
	double x,y;
	double r;
	public:
		friend ostream &operator << (ostream &out,Round &l);
		friend istream &operator >> (istream &in,Round &l);
};
ostream &operator << (ostream &out,Round &l){
	out<<"ROUND:center corordinate:("<<l.x<<","<<l.y<<"),"<<"radius:"<<l.r<<endl;
	return out;
}
istream &operator >> (istream &in,Round &l){
			cout<<"请依次输入圆的圆心坐标(先x,后y)再输入半径\n" ;
	in>>l.x>>l.y>>l.r;
	return in; 
}
class rectangle{
	double x1,y1;
	double length,width;
	public:
	 	friend ostream &operator << (ostream &out,rectangle &l);
		friend istream &operator >> (istream &in,rectangle &l);
}	;
 ostream &operator << (ostream &out,rectangle &l){
	out<<"RECTANGLE:first corordinate:("<<l.x1<<","<<l.y1<<"),"<<"length:"<<l.length<<"  width:"<<l.width<<endl;
	return out;
}
 istream &operator >> (istream &in,rectangle &l){
	cout<<"请依次输入长方形的一个坐标(先x,后y)再输入长度和宽度\n" ;
in>>l.x1>>l.y1>>l.length>>l.width;
}
int main() {
	line l1;
	Round r1;
	rectangle re1;
	cin>>l1>>r1>>re1;
	ofstream fileout("GraphicInfo.txt",ios::out);
	fileout<<l1<<r1<<re1;
	
	cout<<"stored all infomation into the file named GraphicInfo.txt!"<<endl<<endl;
	ifstream filein("GraphicInfo.txt",ios::in) ;//第六题的内容 读出后显示
	 
	line l2;
	Round r2;
	rectangle re2;
	while(!filein.eof()){
			char read[MAX_LINE];
			filein.getline(read,MAX_LINE);
			cout<<read<<endl;
	}
	cout<<"ALL GRAPHIC MESSAGE OUT\n";

	
	return 0;
}
  1. 读取一个英文的文本文件,统计文本文件中的单词的词频,按照词频从大到小依次输出单词和词频。
/*
   读取一个英文的文本文件,统计文本文件中的单词的词频,按照词频从大到小依次输出单词和词频。
*/ 
#include<bits/stdc++.h>
using namespace std;

int main() {
	ifstream  myin("enfile.txt",ios::in);//in到enfile.txt中 
	unordered_map<string,int> mp;
	while(!myin.eof())
	{
		string temp;
		myin >> temp;
		mp[temp]++;
	}
	
	for(pair<string,int> i:mp){
		cout<<(i.first)<<"出现了"<<(i.second)<<"次\n"; 
	}
	
	
    return 0;
}

字符串(buffer)I/O

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值