C++IO和文件操作

文件

标准的输入输出设备名有哪些?

文件输入类的类名是?

  • Iostream

原理

  • 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);


  1. 分析语句:
cout<<"My name is Jone";
//ostream& operator<<(ostream& dest,char *pSource);

  1. 如果是:
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);

  1. 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
    

输入流

下面我们要讨论流的输入,这是用流读取运算符(即重载的运算符>>)实现的。

  1. 流读取运算符通常会跳过输人流中的空格、tab键、换行符等等的空白字符,稍后将介绍如何改变这种行为。
  2. 当遇到输入流中的文件结束符时,流读取运算符返回0(false);否则,流读取运算符返回对调用该运算符的对象的引用。
  3. 每个输入流都包含一组用于控制流状态(即格式化、出错状态设置等)的状态位。
  4. 当输入类型有错时,流读取运算符就会设置输人流的failbit状态位;
  5. 如果操作失败则设置badbit状态位,后面会介绍如何在I/O操作后测试这些状态位。
  1. 最重要的输出流
  • ostream
  • ofstream
  1. 重要的输入流类
  • istream
  • ifstream
  1. istream的其他成员
  • ignore
#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

  • putback
#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

  • peek
#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

  • 设置浮点数精度
  1. 可以用流操纵算子setprecision或成员函数percision控制小数点后面的位数。
  2. 设置了精度以后,该精度对之后所有的输出操作都有效,直到下一次设置精度为止。
  3. 无参数的成员函数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

  • 设置域宽
  1. 成员函数ios.width设置当前的域宽(即输入输出的字符数)并返回以前设置的域宽。
  2. 如果显示数据所需的宽度比设置的域宽小,空位用填充字符填充。
    ?3. 如果显示数据所需的宽度比设置的域宽大,显示数据并不会被截断,系统会输出所有位。
  3. 域宽设置仅对下一行流读取或流插入操作有效,在一次操作完成之后,城宽又被置回0
  4. 未对所处理的输出数据提供足够的域宽时,输出数据将按需要的域宽进行输出,有可能产生难以阅读的输出结果。
#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


文件打开

  1. 使用构造函数打开
创建流对象时直接打开文件
    eg: ofstream ofile(const char *filename, openmode);
    
  1. 使用成员函数open打开文件
    eg: ofstream ofile;
     ofile.open(const char *filename, openmode)
     

openmode文件打开模式

  1. ios::in 输入(读)模式打开文件
  2. ios:: out输出(写)模式打开文件
  3. ios::app追加模式打开文件
  4. ios::trunc若文件已经存在则清空文件的模式打开文件
  5. ios::binary 二进制方式打开文件
  • 这些标识可以单独使用,也可以组合使用,中间用”或“ 运算符 ”|“ 间隔。
fstream file;
file.open(“example”, ios::out | ios::app | ios::binary);

文件类的默认打开方式

打开文件时,没有指定打开模式时,使用默认的打开方式;

  1. ofstream: ios:: out | ios::trunc
  2. ifstream: ios:: in
  3. 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;
}


文件关闭

  1. 当文件的读写操作完成之后,我们必须将文件关闭以使文件重新变为可访问的。关闭文件时需要调用成员函数close( ),它负责将缓存中的数据排放出来并关闭文件。
  2. 这个函数一旦被调用,原来的流对象就可以被用来打开其他的文件了,这个文件也可以重新被其他的进程访问了。
#include<fstream>
fstream file;
file.open(“example”, ios::out | ios::app | ios::binary);
if(file !=NULL) {
    cout<<“open failed”<<endl;
}
//……. 文件操作
file.close();


文件指针

流指针相关函数

  1. tellg( )和 tellp( )
    返回一个pos_type类型,即整数,分别代表当前读指针(get) 和 写指针(put) 的位置
  1. seekg( pos_type position ) 和 seekp( pos_type position )
    流指针被改变为指向文件开始计算的一个绝对位置,传入的参数类型与函数tellg 和 tellp 的返回值类型相同
  1. 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 “ 来进行链接指定
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容