文件
标准的输入输出设备名有哪些?
文件输入类的类名是?
流
原理
- cout是流的对象,它在iostream头文件中作为全局对象定义
ostream cout(stdout)//标准设备名作为其构造时的参数
- ostream流类对应每个基本数据类型都有友元,它们在iostream中声明:
ostream& operator<<(ostream& dest,char* pSource);
ostream& operator<<(ostream& dest,int source);
ostream& operator<<(ostream& dest,char source);
- 分析语句:
cout<<"My name is Jone";
//ostream& operator<<(ostream& dest,char *pSource);
- 如果是:
cout<<"this is"<<7
//(cout<<"this is")<<7;
//ostream& operator<<(ostream& dest,int pSource);
- cin是istream的全局对象.istream流类也有若干个友元;
istream& operator>>(istream& dest,char* pSource);
istream& operator>>(istream& dest,int source);
istream& operator>>(istream& dest,char source);
- C++的类ostream提供了格式化输出和无格式输出的功能
- 用流插入运算符输出标准类型的数据;
- 用成员函数put输出字符;
- 成员函数write的无格式化输出;
- 输出十进制、八进制、十六进制格式的整数;
- 输出各种精度的浮点数、输出强制带有小数点的浮点数,以及用科学计数法和定点计数法表示的浮点数;
- 输出在指定域宽内对齐的数据;
- 输出在域宽内用指定字符填充空位的数据;
- 输出科学计数法和十六进制计数法中的大写字母。
int g=0;
int fun()
{
return ++g;
}
int main(int argc, char **argv)
{
cout<<fun()<<fun()<<fun()<<fun()<<endl;
return 0;
}
//结果为:
//4321
输出流注意事项
上例中输出的顺序有如下规律:
计算顺序: 自右向左
输出顺序: 自左向右
cout 在执行时相当于一个函数,而即将输出的4 个fun( ) 函数相当参数,编译器在函数调用时的入栈顺序是从右向左的,所以在指向fun( )函数时,依次从右向左执行,执行完fun( )函数之后,cout输出各个参数返回的值,此时又是从左至右进行输出,所以函数的执行结果为:4321
输入流
下面我们要讨论流的输入,这是用流读取运算符(即重载的运算符>>)实现的。
- 流读取运算符通常会跳过输人流中的空格、tab键、换行符等等的空白字符,稍后将介绍如何改变这种行为。
- 当遇到输入流中的文件结束符时,流读取运算符返回0(false);否则,流读取运算符返回对调用该运算符的对象的引用。
- 每个输入流都包含一组用于控制流状态(即格式化、出错状态设置等)的状态位。
- 当输入类型有错时,流读取运算符就会设置输人流的failbit状态位;
- 如果操作失败则设置badbit状态位,后面会介绍如何在I/O操作后测试这些状态位。
- 最重要的输出流
- 重要的输入流类
- istream的其他成员
#include<iostream>
using namespace std;
int main()
{
string s;
cout<<"请输入一个字符串:";
//1.忽略输入缓存区中的钱八个字符
//2.在前八个字符中存在结束字符,那么就忽略
//输入缓冲区 结束字符 之前的字符
cin.ignore(8,' ');//设置' '为结束字符
cin>>s;
cout<<"string = "<<s<<endl;
return 0;
}
//结果为
//1.请输入一个字符串:1234567890
//string = 90
//2.请输入一个字符串:12 345
//string = 345
#include<iostream>
using namespace std;
int main()
{
char ch;
cin.putback('a');//将字符a放入到输入缓存流
cout<<"请输入一个ch数据:";
cin>>ch;
cout<<"ch = "<<ch<<endl;
return 0;
}
//结果为:
//请输入一个ch数据:ch = a
#include<iostream>
using namespace std;
int main()
{
int i;
string s;
//获得输入缓冲区中的第一个字符
cout<<"start"<<endl;
char ch=cin.peek();
cout<<"end"<<endl;
if(ch>='0'&&ch<='9')
{
cin>>i;
cout<<"int i = "<<i<<endl;
}
else
{
cin>>s;
cout<<"string s = "<<s<<endl;
}
}
//结果为:
//1.start
//123
//end
//int i = 123
//2.start
//asdf
//end
//string s = asdf
//3.start
//1qwr
//end
//int i = 1
- 调用成员函数read、write可实现无格式输入/输出。
char buffe[] =“HAPPY BIRTHDAY”; cout.write(buffer, 10 );
- 成员函数read把指定个数的字符输入到字符数组中。成员函数gcount统计最后输入的字符个数。
cin.read( buffer, 20 ); //读入20个字符
cout.write( buffer, cin.gcount() ); //输出输入的所有字符
流操作算子
int i=11;
cout<<hex<<i<<endl;//结果为:b(转换为十六进制)
cout<<oct<<i<<endl;//结果为:13(转换为8进制)
cout<<hex<<i<<" "<<dec<<14<<endl;//结果为:b 14
return 0;
#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
int i=11;
cout<<hex<<i<<" "<<dec<<14<<endl;
cout<<setbase(8)<<i<<endl;
return 0;
}
//结果为:
//b 14
//13
#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
int i=11;
// cout<<hex<<i<<endl;//结果为:b(转换为十六进制)
// cout<<oct<<i<<endl;//结果为:13(转换为8进制)
cout<<hex<<i<<" "<<dec<<i<<endl;
cout<<setbase(8)<<i<<endl;
return 0;
}
//结果为:
//b 11
//13
#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
int i=11;
cout<<hex<<i<<" "<<dec<<i<<endl;
cout<<setbase(16)<<i<<endl;
return 0;
}
//结果为:
//b 11
//b
- 可以用流操纵算子setprecision或成员函数percision控制小数点后面的位数。
- 设置了精度以后,该精度对之后所有的输出操作都有效,直到下一次设置精度为止。
- 无参数的成员函数percision返回当前设置的精度。
#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
double root2=3.14159265;
for(int places=0;places<=9;places++)
{
cout<<setprecision(places)<<root2<<"\n";
}
return 0;
}
//结果为:
//3
//3
//3.1
//3.14
//3.142
//3.1416
//3.14159
//3.141593
//3.1415927
//3.14159265
- 成员函数ios.width设置当前的域宽(即输入输出的字符数)并返回以前设置的域宽。
- 如果显示数据所需的宽度比设置的域宽小,空位用填充字符填充。
?3. 如果显示数据所需的宽度比设置的域宽大,显示数据并不会被截断,系统会输出所有位。
- 域宽设置仅对下一行流读取或流插入操作有效,在一次操作完成之后,城宽又被置回0
- 未对所处理的输出数据提供足够的域宽时,输出数据将按需要的域宽进行输出,有可能产生难以阅读的输出结果。
#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
int t1[5]={12345,1,3333,22,999};
int t2[5]={2,22,333,4444,55};
for(int i=0;i<5;i++)
{
cout.width(6);
cout<<t1[i];
}
cout<<endl;
for(int j=0;j<5;j++)
{
cout.width(6);
cout<<t2[j];
}
cout<<endl;
return 0;
}
//结果为:
//12345 1 3333 22 999
// 2 22 333 4444 55
#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
char n[30]={0};
cin.width(5);
while(cin>>n)
{
cout<<"n = "<<n<<endl;
cin.width(5);
}
return 0;
}
//结果为:
//(1)1234
//n = 1234
//(2)12345
//n = 1234
//n = 5
//(3)1234567890123
//n = 1234
//n = 5678
//n = 9012
//n = 3
#include<iostream>
#include<iomanip>
using namespace std;
ostream& tab(ostream& output )
{
return output<<'\t';
}
int main()
{
cout<<'a'<<tab<<'b'<<'\t'<<'c'<<endl;
return 0;
}
//结果为:
//a b c
文件指针
验证流状态
bool bad( )//读写的过程中出错,返回true
bool fail( )//读写的过程出错,或者格式读取错误也会返回true
bool eof( //读文件到末尾时,返回true
bool good( )//文件读写正常返回true
//若想重置以上成员函数检查的状态标志,可以使用clear( ) 函数
#include<iostream>
#include<iomanip>
using namespace std;
#include<limits>
int main()
{
int a;
int b;
cin>>a;
cout<<"a = "<<a<<endl;
cout<<"cin1 = "<<cin.good()<<endl;
if(!cin.good())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
}
cout<<"cin2 = "<<cin.good()<<endl;
cin>>b;
cout<<"b = "<<b<<endl;
return 0;
}
//结果为:
//(1)g
//a = 0
//cin1 = 0
//cin2 = 1
//12
//b = 12
//(2)12
//a = 12
//cin1 = 1
//cin2 = 1
//23
//b = 23
文件打开
- 使用构造函数打开
创建流对象时直接打开文件
eg: ofstream ofile(const char *filename, openmode);
- 使用成员函数open打开文件
eg: ofstream ofile;
ofile.open(const char *filename, openmode)
openmode文件打开模式
- ios::in 输入(读)模式打开文件
- ios:: out输出(写)模式打开文件
- ios::app追加模式打开文件
- ios::trunc若文件已经存在则清空文件的模式打开文件
- ios::binary 二进制方式打开文件
- 这些标识可以单独使用,也可以组合使用,中间用”或“ 运算符 ”|“ 间隔。
fstream file;
file.open(“example”, ios::out | ios::app | ios::binary);
文件类的默认打开方式
打开文件时,没有指定打开模式时,使用默认的打开方式;
- ofstream: ios:: out | ios::trunc
- ifstream: ios:: in
- fstream: ios:: in | ios:: out
对于ifstream 的流对象在打开文件时即使指定的模式中没有显示的标明ios::in 模式,ios::in 标识也一直存在
#include<iomanip>
using namespace std;
#include<fstream>
int main()
{
ifstream ifile("/home/jiangxiubi/1612/jxb");
char sztext[20];
double price;
ifile>>sztext>>price;
cout<<sztext<<" "<<price;
ifile.close()
/*ofstream ofile("/home/jiangxiubi/1612/jxb");
ofile<<"pear"<<" "<<4.5;
ofile.close();*/
return 0;
}
//结果为:在文件jxb中显示pear 4.5
#include<iostream>
#include<iomanip>
using namespace std;
#include<fstream>
int main()
{
ifstream ifile("/home/jiangxiubi/1612/jxb1",ios::in|ios::binary);
char temp[20];
ifile.read(temp,20);
cout<<temp<<endl;
ifile.close();
/* ofstream ofile("/home/jiangxiubi/1612/jxb1",ios::out|ios::binary);
char temp[20]="nihao";
ofile.write(temp,20);
ofile.close();*/
return 0;
}
文件关闭
- 当文件的读写操作完成之后,我们必须将文件关闭以使文件重新变为可访问的。关闭文件时需要调用成员函数close( ),它负责将缓存中的数据排放出来并关闭文件。
- 这个函数一旦被调用,原来的流对象就可以被用来打开其他的文件了,这个文件也可以重新被其他的进程访问了。
#include<fstream>
fstream file;
file.open(“example”, ios::out | ios::app | ios::binary);
if(file !=NULL) {
cout<<“open failed”<<endl;
}
//……. 文件操作
file.close();
文件指针
流指针相关函数
- tellg( )和 tellp( )
返回一个pos_type类型,即整数,分别代表当前读指针(get) 和 写指针(put) 的位置
- seekg( pos_type position ) 和 seekp( pos_type position )
流指针被改变为指向文件开始计算的一个绝对位置,传入的参数类型与函数tellg 和 tellp 的返回值类型相同
- seekg( offset, seekdir) 和 seekp( offset, seekdir)
从由参数seekdir 设定的位置开始计算一个位移 offset,其中seekdir的值可以是: ios::beg(流开始的位置),ios::cur(流当前的位置),ios::end(流末尾的位置)
#include<iostream>
#include<fstream>
using namespace std;
int main()
{
ifstream ifile("/home/jiangxiubi/1612/jxb.txt");
if(NULL==ifile)
{
cout<<"打开文件失败"<<endl;
return -1;
}
//定位函数 -get指针(读指针)
ifile.seekg(0,ios::end);
//指针位置函数 -get 指针(读指针)
cout<<"get point position:"<<ifile.tellg()<<endl;
ifile.close();
return 0;
}
extern
extern “ C ”
extern 是c/c++
- 语言中表明函数或全局变量作用范围的关键字,该关键字告诉编译器此,其声明的函数和变量可以在本模块或其他模块中使用
在c++的环境下使用c
- 的函数时,通常会出现编译器无法找到 obj 模块中的c 函数定义的问题,从而导致链接失败。这时因为在c++ 中支持函数重载,编译时会将函数名和参数列表连接起来,而c 语言不会,因此会造成链接失败的情况,此时 c 函数就需要使用extern “C “ 来进行链接指定