精华内容
下载资源
问答
  • c++文件输入输出流
    千次阅读
    2022-03-23 10:15:11


    前言

    最近在准备复试,学习c++,就当作是学习笔记了


    `

    一、流

    C++的I/O是以一连串的字节流的方式进行的。在输入操作中,字节从设备(例如,键盘、磁盘驱动器、网络连接等)流向内存。在输出操作中,字节从内存流向设备(例如,显示屏、打印机、磁盘驱动器、网络连接等)。
    应用程序通过字节传达信息。字节可以组成字符、原始数据、图形图像、数字语音、数字视频或者任何应用程序所需要的其他信息。系统I/O结构应该能持续可靠地将字节从设备传输到内存,反之亦然。这种传输一般包含一些机械运动,例如,磁盘或磁带的旋转,或者键盘的敲击。数据传输所花费的时间远远大于处理器内部处理数据所花费的时间。所以I/O操作需要仔细计划和协调,以保证最优的性能。
    C++同时提供“低层次的”和“高层次的”I/O功能。

    低层次的I/O功能(也就是非格式化的I/O)指定字节应从设备传输到内存还是从内存传输到设备。这种传输通常针对单个字节。这种低层次的L/0提供速度快、容量大的传输,但是对程序员来说并不方便。
    高层次的I/O(也就是格式化的I/O)。在这种输出方式中字节被组成了有意义的单元,例如整数、浮点数、字符、字符串和用户定义类型。除了大容量的文件处理之外,这种面向类型的方法能够满足绝大多数的I/O处理。

    1.iostream 库的头文件

    <iostream >头文件定义了cin 、 cout 、cerr和 clog对象,分别对应于标准输入流、标准输出流、无缓冲的标准错误流和有缓冲的标准错误流。同时还提供了非格式化和格式化的LO服务。

    <iomanip>头文件中声明了参数化流操纵符(例如setw和 setprecision)用于向格式化I/O提供有用的服务。
    <fstream>头文件声明了文件处理服务。

    2.输入/输出流的类和对象

    预定义对象cin是一个 istream实例,并且“被连接到”(或者“被绑定到”)标准输入设备,通常是键盘。在下面的语句中,流提取运算符(>>)用于使一个整型变量 grade的值(假设grade已经被声明为int变量)从cin输入到内存:
    cin >> grade;
    注意,由编译器确定grade的数据类型,并选择适当的流提取运算符重载。假设grade已经被正确地声明,流提取运算符不需要附加的类型信息(例如,像C语言的I/O的方式)。重载>>运算符用来输入内置类型、字符串和指针的值。
    预定义对象cout是一个ostream实例,并且“被连接到”标准输出设备,通常是显示屏。在下面的语句中,使用流插人运算符(<<)将变量grade的值从内存输出到标准输出设备:
    cout << grade
    注意,也是由编译器确定grade的数据类型(假设grade已经被正确地声明)并且选择合适的流插入运算符,因此流插入运算符也同样不需要附加类型信息。重载<<运算符用来输出内置类型、字符串和指针的值。
    预定义对象cerr是一个ostream 实例,并且“被连接到”标准错误设备。对象cerr的输出是无缓冲的。这意味着每个针对cerr的流插入的输出必须立刻显示,这对于迅速提示用户发生错误非常合适。
    预定义对象clog是一个ostream 实例,并且“被连接到"标准错误设备。clog 的输出是有缓冲的。这意味着每个针对clog中的流插入的输出将保存在缓冲区中,直到缓冲区填满或是被清空才会输出。在操作系统课程上曾讨论过,使用缓冲技术可以加强I/O的性能。

    二、输出流

    ostream提供了格式化的和非格式化的输出功能。输出功能包括使用流插入运算符(<<)执行标准数据类型的输出;通过成员函数put进行字符输出;通过成员函数write进行非格式化的输出;十进制、八进制、十六进制格式的整数输出;具有不同精确度的浮点数的输出,或是具有强制小数点的浮点数的输出,以及以科学记数和定点小数格式的输出;指定宽度数据的输出;用指定符号填充数据域的输出;以及使用科学记数和十六进制符号表示的大写字母的输出。

    使用成员函数put进行字符输出

    可以使用成员函数put输出字符。例如,语句
    cout.put(“A’);
    显示单个字符A。put也可以级联使用。例如,语句
    cout.put( ‘A’ ).put( ‘\n’ );
    输出一个字母A,接着输出一个换行符。前面的语句就以像使用<<一样的方式执行,因为点运算符(.)是从左向右执行,put 成员函数给ostream对象( cout)返回一个引用,该对象接受了put的调用。也可以用代表一个ASCII值的数字表达式作为参数来调用put成员函数,例如,语句
    cout.put( 65 );
    的输出也是A。

    三、输入流

    1.get函数

    三种get

    没有实参的成员函数 get从指定流输入一个字符(包括空白字符及其他非图形字符,比如表示文件尾的键序列等),并将这个值作为函数调用的返回值返回。get函数在遇到流中的文件尾时返回EOF值。
    带一个字符引用参数的get 函数将输入流中的下一个字符(即使它是一个空白字符)输人,并将它存诸在其引用的字符参数内。在调用这个版本的get 函数时将给调用它的istream对象返回一个引用。
    get 函数拥有三个参数:一个字符数组、一个数组长度限制和一个分隔符(默认值为‘\n’)。这个函数可以从输入流读取多个字符,它可以读取“数组最大长度-1"个字符后终止,也可以遇到分隔符就终止。在程序中,插入一个空字符用来结束字符数组中的输入字符串,字符数组在程序中作为缓冲区。**分隔符没有放置在字符数组中,而是保留在输入流中(分隔符是下一个被读取的字符)。**因此,第二次 get 函数调用所得的结果将是个空行,除非将分隔符从输人流中移出(可以使用cin.ignore( ))。

    2. getline

    成员函数getline操作与第三个版本的成员函数get类似,在该行所存储的字符数组的末尾插入一个空字符。getline函数从流中移除分隔符(也就是读取该字符然后丢弃),没有将其放在字符数组内存储。

    四、使用read、write和gcount的非格式化的I/O

    非格式化的输入/输出使用的分别是istream与 ostream 的成员函数read和 write。成员函数read将一定数量的字节读入到字符数组中,
    成员函数write则从字符数组中输出字节。这些字节没有经过任何格式化,它们就像原始字节一样输入或输出。例如,命令
    char buffer[ ] =“HAPPY BIRTHDAY”;
    cout.write( buffer,10);
    输出 buffer数组中的前10个字符(包括空字符,任何一个空字符都会导致使用cout和<<进行输出操作的终止)。调用
    cout.write(“ABCDEFGHIJKLMNOPQRSTUVWXYZ”,10);
    显示字母表的前10个字母。
    成员函数read将指定数量的字符读入到字符数组中。当读取的字符数量少于指定数量时,failbit将被设置

    五、流操纵符

    浮点精度(precision,setprecision)

    可以使用流操纵符setprecision或ios_base的成员函数 precision来控制浮点数的精度(也就是小数点右边的位数)。调用这两者之中的任何一个都可以改变输出精度,这将影响后面所有的输出操作,直到下一个设置精度操作被调用为止。调用无参数的成员函数 precision将返回当前的精度设置(这样可以在不再使用“黏性的"设置时,重新使用原来的精度设置)。

    域宽( width, setw)

    成员函数width(基类是ios_base)可以设置域宽(也就是输出值所占的字符位数或是可输入的最大字符数)并且返回原先的域宽。如果输出值的宽度比域宽小,则插入填充字符进行填充。宽度大于指定宽度的值不会被截短,会将整个值都打印出来。不含参数的width函数将返回当前域宽。
    宽度设置只适用于下一次输入或输出(也就是说宽度设置并不是“黏性的”),之后的宽度被隐式地设置为0(也就是输入和输出将使用默认设置)。一次宽度设置适用于所有后续输出的假设是逻辑错误。

    对齐(left、right 和 internal)

    流操纵符left和right分别使域左对齐并在其右边填充字符,或者右对齐并在其左边填充字符。填充字符由成员函数fill或是参数化流操纵符setill指定
    流操纵符internal 表示数字的符号(或是使用showbase流操纵符显示的基数)应当左对齐,同时数字的数值部分应右对齐,而中间的部分则使用填充字符填充。

    内容填充( fill , setfill)

    成员函数fill 指定对齐域的填充字符。如果没有字符被指定,则使用空格符填充。fill函数返回设定之前的填充字符。setill操纵符也用于设置填充字符。

    更多相关内容
  • 主要为大家总结了C++输入输出流文件流操作,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • C++文件输入/输出流

    千次阅读 2022-03-24 19:16:48
    文章目录文件输入/输出流类表5: 文件读写模式表6:ios_base 标识的组合意义ofstream:写入文件的流类例8:输出文本文件例9:输出二进制文件ifstream:从文件中读取的流类例10:输入文本文件例11:输入二进制文件表7:...

    文件输入/输出流类

    C++ 提供以下类来执行文件的字符输出和输入:

    • ofstream:写入文件的流类
    • ifstream:从文件中读取的流类
    • fstream:流类以读取和写入文件。
    表5: 文件读写模式
    读写模式意义
    ios::in打开输入操作(ifstream的默认模式)。
    ios::out打开以进行输出操作(ofstream的默认模式)。
    ios::binary以二进制模式打开。
    ios::ate在文件末尾设置初始位置。 如果未设置此标志,则初始位置是文件的开头。
    ios::app所有输出操作都在文件末尾执行,将内容附加到文件的当前内容。
    ios::trunc如果打开文件以进行输出操作并且它已经存在,则删除其先前的内容并用新的内容替换。
    表6:ios_base 标识的组合意义
    ios_base 标识意义C模式
    in读取 (文件必须存在)“r”
    out清空之后改写 (有必要才产生)“w”
    out | trunc清空之后改写 (有必要才产生)“w”
    out | app添加 (有必要才产生)“a”
    in | out读和写: 最初位置在起始点 (文件必须存在)“r + ”
    in | out | trunc先清空, 再读写 (有必要才产生)“w+”
    ofstream:写入文件的流类
    例8:输出文本文件
    #include <iostream>
    #include <iomanip>
    #include <vector>
    #include <string>
    #include <fstream>
    
    int main()
    {
        std::vector<std::string> fruit{ "火龙果","梨" };
        std::vector<double> price{ 3.02,4.51 };
        //使用输出至显示器
        std::cout << "水果名 单价\n" << std::setiosflags(std::ios::left);
        for (int i = 0; i < 2; ++i)
        {
            std::cout << std::setw(8) << fruit[i];
            std::cout << std::setw(6) << price[i];
            std::cout << std::endl;
        }
        // 使用文件输出流类ofstream的文件对象fout将数据输出到文本文件price.txt
        std::ofstream fout; //文件输出流类ofstream对象fout需要程序员自己定义
        fout.open("price.txt",std::ios::out);//打开文件price.txt,如文件不存在则创建新文件
        fout << "水果名 单价\n" << std::setiosflags(std::ios::left);
        for (int i = 0; i < 2; ++i)
        {
            fout << std::setw(8) << fruit[i];
            fout << " ";
            fout << std::setw(6) << price[i];
            fout << std::endl;
        }
        fout.close(); //关闭所打开的文件price.txt
        return 0;
    }
    

    结果:

    水果名 单价
    火龙果  3.02
    梨      4.51
    
    例9:输出二进制文件
    #include <iostream>
    #include <iomanip>
    #include <string.h>
    #include <fstream>
    
    int main()
    {
        char *fruit[] = { "火龙果","梨" };
        double price[] = { 3.02,4.51 };
        char str[7];
        //使用文件对象fout将数据输出到二进制文件price.dat
        std::ofstream fout; //文件输出流类ofstream对象fout需要程序员自己定义
        fout.open("price.dat",std::ios::out|std::ios::binary);//以二进制模式打开文件price.dat,如文件不存在则创建新文件
        for (int i = 0; i < 2; ++i)
        {
            strcpy(str,fruit[i]);
            fout.write(str,sizeof(str));//输出水果名
            fout.write((char*)(&price[i]),sizeof(double));//输出价格
        }
        fout.close(); //关闭所打开的文件price.dat
        return 0;
    }
    
    
    ifstream:从文件中读取的流类
    例10:输入文本文件
    #include <iostream>
    #include <fstream>
    
    int main()
    {
        char fruit[20];
        double price;
        std::ifstream fin; //使用文件输入流类ifstream的文件对象fin从文本文件price.txt中输入数据
        fin.open("price.txt"); //打开文本文件
        if(fin.is_open()==false) //检查打开文件是否成功
            std::cout<<"打开文件price.txt失败"<<std::endl;
        else
        {
            fin.getline(fruit,19); //读出标题行
            std::cout<<fruit<<std::endl; //显示所读出的标题行,显示结果:水果名称单价
    
            for(int i=0;i<2;++i)
            {
                fin>>fruit>>price; //从文件price.txt中读取水果名称和单价
                std::cout<<fruit<<","<<price<<std::endl; //显示水果名称和单价,验证输入结果
            }
            fin.close(); //关闭所打开的文件price.txt
        }
    
        return 0;
    }
    
    

    结果:

    水果名 单价
    火龙果,3.02
    梨,4.51
    
    例11:输入二进制文件
    #include <iostream>
    #include <iomanip>
    #include <fstream>
    
    int main()
    {
        char name[20];
        double num;
        std::ifstream fin; 
        fin.open("price.dat",std::ios::in |std::ios::binary);
        for (int i = 0; i < 2; ++i)
        {
            fin.read(name,7);
            fin.read((char*)(&num),8);
            std::cout<<name<<" "<<num<<std::endl;
        }
        fin.close(); //关闭所打开的文件price.dat
        return 0;
    }
    

    结果:

    火龙果 3.02
    梨 4.51
    
    表7:检查流的特定状态
    成员函数意义
    good检查是否没有发生错误,
    eof检查是否到达了文件末尾
    fail检查是否发生了可恢复的错误
    bad检查是否已发生不可恢复的错误
    例12:检查输入文件状态
    #include <iostream>
    #include <fstream>
    
    int main()
    {
        char ch;
        std::ifstream fin; //使用文件输入流类ifstream的文件对象fin从文本文件price.txt中输入数据
        fin.open("price.txt"); //打开文本文件
        while(true)
        {
            fin.get(ch); //从文件price.txt中每次读取一个字符
            //eof的返回值:true-文件已结束,false-文件未结束
         	//good的返回值:true-文件正常,false-文件已损坏
            if(fin.eof()==true||fin.good()==false)
                break; //结束文件输入
            std::cout <<ch; //显示所读出的字符ch
        }
        fin.close(); //关闭所打开的文件price.txt
        return 0;
    }
    
    

    结果:

    水果名 单价
    火龙果   3.02
    梨       4.51
    
    fstream:流类以读取和写入文件
    表 8: 文件定位标志
    模式标志描述
    ios::beg从文件头开始计算偏移量
    ios::end从文件末尾开始计算偏移量
    ios::cur从当前位置开始计算偏移量
    随机读写文件

    打开文件后,文件对象与外存文件建立起关联关系。此时,文件对象内部将保存当前读写数据的位置信息。该位置信息保存在被称作文件指针的数据成员中。文件输入流对象包含一个读文件指针,文件输出流对象包含一个写文件指针,而文件输入/输出流对象则分别包含一个读文件指针和一个写文件指针。
    通常情况下,打开文件后文件对象的读/写指针都定位于文件头的位置。每执行一次读/写操作,读/写指针将自动后移,移到下一次读/写数据的位置。这就是文件的顺序读/写。
    可以调用函数成员seekg和tellg来移动或读取读文件指针的位置,调用函数成员seekp知和tellp来移动或读取写文件指针的位置。程序员通过移动读/写指针,可实现对文件的随机读写。

    这4个与文件指针相关函数的原型如下:

    文件指针相关函数描述
    istream& seekg(long bytes,ios::seek dir origin )移动读文件指针
    long tellg()返回当前读文件指针的位置
    ostream& seekp(long bytes,ios::seek_dir origin )移动写文件指针
    long tellp()返回当前写文件指针的位置

    例13:随机读写文件

    #include <iostream>
    #include <fstream>
    
    int main()
    {
        char fruit[20];
        double price;
        std::ifstream fin; 
        fin.open("price.dat"); //打开二进制文件
        if(fin.is_open()==false) //检查打开文件是否成功
            std::cout<<"打开文件price.dat失败"<<std::endl;
        else
        {
            for(int i=0;i<2;++i)
            {
                fin.read(fruit,7); 
                //std::cout << fin.tellg() << '\n'; 
                fin.read((char*)&price,8);
                std::cout << fin.tellg() << '\n'; //当前读文件指针的位置
                std::cout<<fruit<<","<<price<<std::endl; //显示水果名称和单价,验证输入结果
            }
            fin.seekg(-30L,std::ios::end);//从文件尾向前(即往回)移动两行(一行有15个字节)
            fin.read(fruit,7); 
            std::cout<<fruit<<std::endl;
            fin.seekg(8L,std::ios::cur);//当前位置开始向后移动7个字节
            fin.read(fruit,7); 
            std::cout<<fruit<<std::endl;
            fin.close(); //关闭所打开的文件price.dat
        }
        return 0;
    }
    
    

    结果:

    15
    火龙果,3.02
    30
    梨,4.51
    火龙果
    梨
    

    参考资料:

    《大道至简—c++stl(标准模板库)精解》

    《c++语言程序设计》(第2版)

    http://c.biancheng.net/view/1541.html

    https://zh.cppreference.com/w/cpp/io/basic_fstream

    展开全文
  • C++文件输入输出,看这一篇就够了

    千次阅读 2022-04-30 21:56:11
    C++文件输入输出,看这一篇就够了 1 简介 1.1 继承关系 基类->继承类: ​ ios->ostream->ofstream ​ ios->istream->ifstream ​ iostream->fstream(还继承了两个缓冲区,一个用于输入,一个用于...

    1 简介

    1.1 继承关系

    基类->继承类:

    ​ ios->ostream->ofstream

    ​ ios->istream->ifstream

    ​ iostream->fstream(还继承了两个缓冲区,一个用于输入,一个用于输出)(此类用于文件I/O的同步,即协调地移动输入缓冲区的输入指针和输出缓冲区的输出指针)(输入输出模式时使用fstream类)

    1.2 流

    C++程序将文件输入和输出看作字符流;对于输入来说,程序从输入流中抽取字符,对于输出来说,程序向输出流中插入字符。流是程序与流源或流目的之间的中介,这样C++就可以对来源不同的字符做相同处理。

    1.3 缓冲区

    缓冲区就是一块存储空间,它是为了匹配程序处理速度和外设处理速度;比如程序一次处理1byte,但是磁盘一次读取512bytes;又或者程序一次处理1byte,可以1byte地从磁盘读取,但是由于硬件读取一次数据复杂且操作慢,因此使用缓冲区可以加快程序处理速度。

    flushing the buffer:刷新缓冲区就是清空缓冲区地内容以备下次使用。

    文件输出输入使用缓冲区,在声明每个ofsream or ifsream对象时程序会为其自动分配该对象自己的缓冲区;使用缓冲区可以提高文件输出速度。
    何时清空缓存:
    1.缓存区满时
    2.使用文件close()方法时,为了保证关闭文件时文件被更新。

    2 输入输出流状态

    流状态被定义为iostate,是由三个ios_base组成:eofbit, badbit, 和failbit,三者都为一位可以设置位1(设置)或0(清除)。当三者都为0时说明一切顺利。

    成员描述
    eofbit当读取文件到达文件尾时置为1
    failbit当输入流中的数据类型和目的数据类型不一致时置为1;I/O错误(读取一个不允许访问的只读磁盘或打开一个不存在的文件)时置为1
    badbit在一些无法诊断的失败破坏流时置为1
    goodbit另一种说明0的方法
    good()如果流可以使用,则返回true,反之返回false
    eof()如果eofbit被设置,则返回true,反之返回false
    bad()如果badbit被设置,则返回true,反之返回false
    fail()如果failbit或badbit被设置,返回true,反之返回false
    rdstate()返回流状态
    exceptions()返回一个位掩码,指出哪些标记导致异常被引发
    exceptions(iostate ex)设置哪些状态将导致clear()引发异常
    clear(iostate s)将流状态设置为s,s的默认值为0;如果rdstate() & exceptions()) != 0,将抛出basic_ios::failure异常;将会设置s,但是其他的会被置0
    setstate (iostate s)调用clear(rdstate()|s)。这将设置与s中设置的位对应的流的状态位,其他流状态保持不变。

    2.1 设置状态

    setstate()的主要目的是提供一种修改状态的途径。例如,如果num是一个int,则下面的调用将可能导致operator>>(int &)使用setstate()设置failbit或eofbit。

    clear();//清除所有的位
    clear(eofbit);//清楚指定的位
    setstate(eofbit);//设置指定的位
    //等等
    

    2.2 文件尾EOF

    文件尾 EOF
    如果输入来自于文件:使用文件尾(EOF)判断文件是否读完。
    当检测到EOF之后:cin将eofbit和failbit都设置为1;同时,将设置cin对象中的一个指示EOF条件的标记,设置这个标记后,cin将不读取输入,直到cin.clear()。
    EOF被定义为值为-1,因此不能将EOF赋给char类型,因为char类型没有符号,需要使用int类型接收EOF。

    举例:Windows允许通过键盘模拟文件尾:Ctrl+Z

    3 文件传输模式

    ios_base定义了openmode类型表示模式,类似于fmtflags和iostate类型,是bitmask类型。

    文件模式常量:

    ConstantMeaning
    ios_base::in读取文件
    ios_base::out写入文件
    ios_base::ate打开文件时文件指针指向文件尾
    ios_base::app在文件尾添加内容
    ios_base::trunc如果文件存在则截断它
    ios_base::binary二进制文件

    文件模式组合(|符号表示联合两个二进制为一个值,该值可以表达两个二进制模式)

    C++ 模式C模式含义
    ios_base::in“r”读文件模式
    ios_base::out“w”与ios_base::out | ios_base::trunc一样
    ios_base::out | ios_base::trunc“w”写文件模式,并且在打开文件时截断文件(将文件置为空)
    ios_base::out | ios_base::app“a”追加模式,将文件指针指向文件尾,向末尾添加内容;原始数据不可修改
    ios_base::in | ios_base::out“r+”打开以读写,在文件允许的位置写入
    ios_base::in | ios_base::out | ios_base::trunc“w+”打开以读写,如果文件已经存在,则首先截断文件
    c++mode | ios_base::binary“cmodeb”在C++模式和二进制模式打开
    c++mode | ios_base::ate“cmode”以指定的模式打开,并将文件指针移到文件尾。

    模式的使用方法:

    //第二个参数指定模式
    //ifstream fin(filename, c++mode);
    //fopen(filename, cmode);
    ifstream fin("banjo", mode1); // constructor with mode argument
    ofstream fout();
    fout.open("harp", mode2); // open() with mode arguments
    

    ifstream open()的默认模式为ios_base::in;

    ofstream open()的默认模式为ios_base::out | ios_base::trunc;

    fstream无默认模式,因此在创建fstream对象时要显示提高模式实参。

    4 相关函数

    4.1 ofstream对象 or ifstream对象.open(filename)

    可以接受C-风格字符串作为参数,也可以接受存储在数组中的字符串
    默认情况下,当filename所指文件不存在时,open()将在当前程序可执行目录创建名为filename的文件;
    作用:当存在时,open()将首先截断该文件,即删除原有的文件内容,然后再将新内容输出到文件中

    4.2 ofstream对象 or ifstream对象.close()

    作用:无参数,原因是ofstream对象 or ifstream对象已经关联文件,不需要参数;在关闭文件时,不会释放ofstream对象 or ifstream对象的缓冲区,只是解除了ofstream对象 or ifstream对象与文件的关联关系;ofstream对象 or ifstream对象可以重新与其他文件绑定。

    4.3 ofstream对象 or ifstream对象.isopen(filename)

    检查文件filename是否被成功打开;如果成功打开,则返回true;反之(文件不存在等原因),返回false。

    在流状态中的fin.fail()和fin.good()也能检查文件是否被正常打开,但是流状态相关函数不涉及文件传输模式;但是is_open()考虑了文件传输模式,因此is_open()更适用于检查文件是否正常打开。

    4.4 ifstream对象.get(char ch)

    作用:逐个字符获取文件中的内容,并将其赋值给ch;直到遇见文件尾。

    4.5 ofstream对象.write( (char *) &pl, size);

    第一个参数为要写入文件内容的地址(必须转换为char *类型),第二个参数为要写入内容的大小(单位为byte)。

    作用:将pl指向的大小为size的内容复制到ofstream对象绑定的文件中。

    注意事项:这个方法可以用于不含虚函数的类,原因是在这种情况下,只有数据成员被保存,而方法不会被保存;如果类有虚方法,则也将复制隐藏指针(该指针指向虚函数的指针表);由于下一次运行程序时,虚函数表可能在不同的位置,因此将文件中的旧指针信息复制到对象中,可能造成混乱。

    4.6 ifstream对象.read((char *) &pl, size);

    第一个参数为读入文件的存储地址(必须转换为char *类型),第二个参数为要读入内容的大小(单位为byte)。

    作用:将ifstream对象绑定的文件中大小为size的内容pl指向的地址。

    注意事项:这个方法可以用于不含虚函数的类,原因是在这种情况下,只有数据成员被保存,而方法不会被保存;如果类有虚方法,则也将复制隐藏指针(该指针指向虚函数的指针表);由于下一次运行程序时,虚函数表可能在不同的位置,因此将文件中的旧指针信息复制到对象中,可能造成混乱。

    4.7 fstream对象 or istream对象.seekg()

    将输入指针移动至给定文件位置(由于fstream对象使用缓冲区存取中间数据,因此指针指向的实际上是缓冲区的位置,而不是实际的文件)。

    也可以将seekg()用于ifstream对象。

    函数原型:

    第一个原型定位到离第二个参数指定的文件位置的偏移量(单位为字节)的位置,第一个参数off_type为偏移量,第二个参数ios_base::seekdir可以为三个常量—ios_base::beg(相对于文件开始处的偏移)、ios_base::cur(相对于文件当前位置的偏移)、ios_base::end(相对于文件结尾处的偏移);

    第二个原型定位到离文件开头特定距离(单位为字节)的位置,参数pos_type为偏移量。是一个绝对偏移量。

    //模板原型
    basic_istream<charT,traits>& seekg(off_type, ios_base::seekdir);
    basic_istream<charT,traits>& seekg(pos_type);
    //For the char specialization
    istream & seekg(streamoff, ios_base::seekdir);
    istream & seekg(streampos);//streampos包含一个接收streamoff参数的构造函数和一个接收整数参数的构造函数
    
    //eg
    fin.seekg(30, ios_base::beg); // 30 bytes beyond the beginning
    fin.seekg(-1, ios_base::cur); // back up one byte
    fin.seekg(0, ios_base::end); // go to the end of the file
    

    注意:streampos和streampos是off_type和pos_type对于char类型的专门化;同样,针对wistream对象,wstreampos和streamoff类型是off_type和pos_type对于wistream类型的专门化。

    4.8 fstream对象 or ostream对象.seekp()

    将输出指针移动至给定文件位置(由于fstream对象使用缓冲区存取中间数据,因此指针指向的实际上是缓冲区的位置,而不是实际的文件)。

    也可以将seekp()用于ofstream对象。

    将输出指针移动至给定文件位置(由于fstream对象使用缓冲区存取中间数据,因此指针指向的实际上是缓冲区的位置,而不是实际的文件)。

    也可以将seekp()用于ofstream对象。

    函数原型:

    第一个原型定位到离第二个参数指定的文件位置的偏移量(单位为字节)的位置,第一个参数off_type为偏移量,第二个参数ios_base::seekdir可以为三个常量—ios_base::beg(相对于文件开始处的偏移)、ios_base::cur(相对于文件当前位置的偏移)、ios_base::end(相对于文件结尾处的偏移);

    第二个原型定位到离文件开头特定距离(单位为字节)的位置,参数pos_type为偏移量。是一个绝对偏移量。

    //模板原型
    basic_istream<charT,traits>& seekp(off_type, ios_base::seekdir);
    basic_istream<charT,traits>& seekp(pos_type);
    //For the char specialization
    istream & seekp(streamoff, ios_base::seekdir);
    istream & seekp(streampos);//streampos包含一个接收streamoff参数的构造函数和一个接收整数参数的构造函数
    
    //eg
    fin.seekp(30, ios_base::beg); // 30 bytes beyond the beginning
    fin.seekp(-1, ios_base::cur); // back up one byte
    fin.seekp(0, ios_base::end); // go to the end of the file
    

    注意:streampos和streampos是off_type和pos_type对于char类型的专门化;同样,针对wistream对象,wstreampos和streamoff类型是off_type和pos_type对于wistream类型的专门化。

    4.9 fstream对象 or istream对象.tellg()

    返回值为streampos,表示输入指针的当前文件位置(单位为字节),相对于文件开始的偏移量。

    注意:如果创建了fstream对象,由于输入指针和输出指针将同时移动,因此tellg()和tellp()返回值相同;然而,如果使用istream对象来管理输入流,而使用ostream对象管理输出流,则输入指针和输出指针将彼此独立移动,tellg()和tellp()返回值将不同。

    4.10 fstream对象 or ostream对象.tellp()

    返回值为streampos,表示输出指针的当前文件位置(单位为字节),相对于文件开始的偏移量。

    注意:如果创建了fstream对象,由于输入指针和输出指针将同时移动,因此tellg()和tellp()返回值相同;然而,如果使用istream对象来管理输入流,而使用ostream对象管理输出流,则输入指针和输出指针将彼此独立移动,tellg()和tellp()返回值将不同。

    4.11 fstream对象 or ostream对象 or istream对象.seekg(偏移量)

    将文件指针指向距离文件开头 偏移量(单位为字节) 大小的位置。

    可以使用它将文件指针指向文件开头。

    5 简单文件输入输出

    5.1 写入到文本文件中

    步骤:

    • 1 包含fstream头文件,fstream头文件中定义了ofstream类用于处理输出
    • 2 包含std命名空间(ofstream在std命名空间中)
    • 3 定义一个或多个ofstream对象,命名要求符合命名规范,每个ofstream对象都与一个输出流绑定在一起
    • 4 将对象和文件关联起来,方法之一是open()方法,这种关联在对象释放时自动解除
    • 5 文件操作完成时,应使用close()方法关闭文件
    • 6 可以使用ofstream对象和<<操作符输出各种类型的数据,可以使用cout可使用的任何方法(cout使用方法见C++ cout的用法,看这一篇就够了)

    5.2 读取文本文件

    步骤:

    • 1 包含fstream头文件,fstream头文件中定义了ifstream类用于处理输入,ifstream与一个输入流绑定在一起
    • 2 包含std命名空间(ifstream在std命名空间中)
    • 3 定义一个或多个ifstream对象,命名要求符合命名规范,每个ofstream对象都与一个输入流绑定在一起
    • 4 将对象和文件关联起来,方法之一是open()方法
    • 5 文件操作完成时,使用close()方法关闭文件
    • 6 可以使用ifstream对象和>>操作符输出各种类型的数据,可以使用cin可使用的任何方法(cin使用方法见C++ cin的用法,看这一篇就够了)
    • 7 ifstream本身作为测试条件时,如果最后一个读取操作成功,ifstream将被转换为true,否则转换为false

    5.3 C++实例

    5.3.1 cpp代码

    /*
    Project name :			_26File
    Last modified Date:		2022年4月29日22点20分
    Last Version:			V1.0
    Descriptions:			简单文件输入输出
    */
    #include <iostream>
    #include <fstream> // for file I/O,这个头文件包含了iostream头文件,所以此处可以不显示包含iostream头文件
    #include <cstdlib> // support for exit()
    const int SIZE = 60;
    int main()
    {
    	using namespace std;
    	cout << "ofstream*********************************************************************" << endl;
    	char automobile[50];
    	int year;
    	double a_price;
    	double d_price;
    	string filename1;
    	cout << "Enter name for new file: ";
    	cin >> filename1;
    	while (cin.get() != '\n');
    	ofstream outFile; // create object for output
    	outFile.open(filename1.c_str()); // associate with a file  将文件和对象链接起来 
    	//创建对象和连接文件可以使用一个表达式实现:ofstream fout("jar.txt"); // create fout object, associate it with jar.txt
    	cout << "Enter the make and model of automobile: ";
    	cin.getline(automobile, 50);
    	cout << "Enter the model year: ";
    	cin >> year;
    	cout << "Enter the original asking price: ";
    	cin >> a_price;
    	d_price = 0.913 * a_price;
    	// display information on screen with cout
    	cout << fixed;
    	cout.precision(2);
    	cout.setf(ios_base::showpoint);
    	cout << "Make and model: " << automobile << endl;
    	cout << "Year: " << year << endl;
    	cout << "Was asking $" << a_price << endl;
    	cout << "Now asking $" << d_price << endl;
    	// now do exact same things using outFile instead of cout
    	outFile << fixed;
    	outFile.precision(2);
    	outFile.setf(ios_base::showpoint);
    	outFile << "Make and model: " << automobile << endl;
    	outFile << "Year: " << year << endl;
    	outFile << "Was asking $" << a_price << endl;
    	outFile << "Now asking $" << d_price << endl;
    	outFile.close(); // done with file
    	cout << "ifstream*********************************************************************" << endl;
    	while (cin.get() != '\n');
    	char filename[SIZE];
    	ifstream inFile; // object for handling file input
    	cout << "Enter name of data file: ";
    	cin.getline(filename, SIZE);
    	inFile.open(filename); // associate inFile with a file
    	//创建对象和连接文件可以使用一个表达式实现 ifstream inFile(filename);
    	if (!inFile.is_open()) // failed to open file
    	{
    		cout << "Could not open the file " << filename << endl;
    		cout << "Program terminating.\n";
    		exit(EXIT_FAILURE);//EXIT_FAILURE就是一个全局的常量
    		//exit():定义在头文件cstdlib,该头文件还定义了与操作系统通信的参数值EXIT_FAILURE
    	}
    	double value;
    	double sum = 0.0;
    	int count = 0; // number of items read
    	while (inFile>>value) // 判断读取是否成功,读取失败则退出循环
    	{
    		++count; // one more item read
    		sum += value; // calculate running total
    	}
    	//因此在这加两句读取最后一个数据
    	++count; // one more item read
    	sum += value; // calculate running total
    	//检查读取失败的原因
    	if (inFile.eof())
    		cout << "End of file reached.\n";
    	else if (inFile.fail())
    		cout << "Input terminated by data mismatch.\n";
    	else
    		cout << "Input terminated for unknown reason.\n";
    	if (count == 0)
    		cout << "No data processed.\n";
    	else
    	{
    		cout << "Items read: " << count << endl;
    		cout << "Sum: " << sum << endl;
    		cout << "Average: " << sum / count << endl;
    	}
    	inFile.close(); // finished with the file
    
    	return 0;
    }
    

    5.3.2 运行结果

    ofstream*********************************************************************
    Enter name for new file: list.txt
    Enter the make and model of automobile: mobile
    Enter the model year: 2022
    Enter the original asking price: 999
    Make and model: mobile
    Year: 2022
    Was asking $999.00
    Now asking $912.09
    ifstream*********************************************************************
    Enter name of data file: scores.txt
    End of file reached.
    Items read: 13
    Sum: 222.00
    Average: 17.08
    
    D:\Prj\_C++Self\_26File\Debug\_26File.exe (进程 5572)已退出,代码为 0。
    要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
    按任意键关闭此窗口. . .
    

    5.3.3 相关文件信息

    写入的文件内容:list.txt

    Make and model: mobile
    Year: 2022
    Was asking $999.00
    Now asking $912.09
    

    读入的文件内容:scores.txt

    18 19 18.5 13.5 14 16 19.5 20 18 12 18.5
    17.5
    

    6 命令行处理技术

    6.1 简介

    命令行处理程序经常使用命令行参数识别文件,命令行参数是指出现在当在command使用命令行时出现的参数。举例:

    wc report1 report2 report3
    此处wc是程序名,report1 report2 report3是文件名作为命令行参数传递给程序
    

    命令行处理技术也可以在main中使用:

    int main(int argc, char *argv[])
    //argc代表命令行中出现的参数个数,argv是指向 chart * 的指针;argv相当于指针数组,每个指针指向一个命令行参数;argv[0]是命令名,argv[1]指向第一个命令行参数字符串,以此类推
    

    注意事项:命令行参数与命令行操作系统息息相关;很多Windows IDEs提供了命令行参数的选项,如何打开需要研读相关说明文档;很多Windows IDEs都可以生成可执行我呢见,这些文件可以在Windows命令提示符模式下运行。

    6.2 C++实例

    6.2.1 代码

    项目_26_1file_command_arguments

    /*
    Project name :			_26_1file_command_arguments
    Last modified Date:		2022年4月30日09点53分
    Last Version:			V1.0
    Descriptions:			文件操作
    */
    
    #include <iostream>
    #include <fstream> // for file I/O,这个头文件包含了iostream头文件,所以此处可以不显示包含iostream头文件
    #include <cstdlib> // support for exit()
    int main(int argc, char* argv[])
    {
    	using namespace std;
    	
    	cout << "命令行处理技术**************************************************************" << endl;
    	if (argc == 1) // quit if no arguments
    	{
    		cerr << "Usage: " << argv[0] << " filename[s]\n";
    		exit(EXIT_FAILURE);
    	}
    	ifstream fin; // open stream
    	long count1;
    	long total = 0;
    	char ch;
    	for (int file = 1; file < argc; file++)
    	{
    		fin.open(argv[file]); // connect stream to argv[file]
    		if (!fin.is_open())
    		{
    			cerr << "Could not open " << argv[file] << endl;
    			fin.clear();
    			continue;
    		}
    		count1 = 0;
    		while (fin.get(ch))
    			count1++;
    		cout << count1 << " characters in " << argv[file] << endl;
    		total += count1;
    		fin.clear(); // needed for some implementations
    		fin.close(); // disconnect file
    	}
    	cout << total << " characters in all files\n";
    
    	return 0;
    }
    

    6.2.2 如何执行该代码

    首先在VS2022中编译该代码,生成_26_1file_command_arguments.exe可执行文件
    然后在cmd中找到_26_1file_command_arguments.exe可执行文件并执行以下语句将会得到以下结果:

    Microsoft Windows [版本 10.0.19044.1645]
    (c) Microsoft Corporation。保留所有权利。
    C:\Users\15495>d:
    D:\>cd D:\Prj\_C++Self\_26_1file_command_arguments\x64\Debug
    D:\Prj\_C++Self\_26_1file_command_arguments\x64\Debug>_26_1file_command_arguments.exe "list.txt" "carinfo.txt" "scores.txt"
    命令行处理技术**************************************************************
    Make and model: love
    Year: 2022
    Was asking $999.00
    Now asking $912.09
    70 characters in list.txt
    Make and model: kaaha
    Year: 2022
    Was asking $999.00
    Now asking $912.09
    71 characters in carinfo.txt
    18 19 18.5 13.5 14 16 19.5 20 18 12 18.5
    17.545 characters in scores.txt
    186 characters in all files
    
    D:\Prj\_C++Self\_26_1file_command_arguments\x64\Debug>
    

    6.3.3 相关文件信息

    carinfo.txt

    Make and model: kaaha
    Year: 2022
    Was asking $999.00
    Now asking $912.09
    

    list.txt

    Make and model: love
    Year: 2022
    Was asking $999.00
    Now asking $912.09
    

    scores.txt

    18 19 18.5 13.5 14 16 19.5 20 18 12 18.5
    17.5
    

    7 向文件追加内容(追加模式举例)

    7.1 代码

    /*
    Project name :			_26File
    Last modified Date:		2022年4月30日10点05分
    Last Version:			V1.0
    Descriptions:			向文件追加内容
    */
    
    #include <iostream>
    #include <fstream> // for file I/O,这个头文件包含了iostream头文件,所以此处可以不显示包含iostream头文件
    #include <cstdlib> // support for exit()
    #include <string>
    int main(int argc, char* argv[])
    {
    	using namespace std;
    	cout << "向文件追加内容*********************************************************************" << endl;
    	char ch;
    	const char* file = "guests.txt";
    	// show initial contents
    	ifstream fin;
    	fin.open(file);
    	if (fin.is_open())
    	{
    		cout << "Here are the current contents of the "
    			<< file << " file:\n";
    		while (fin.get(ch))
    			cout << ch;
    		fin.close();
    	}
    	// add new names
    	ofstream fout(file, ios::out | ios::app);//追加模式
    	if (!fout.is_open())
    	{
    		cerr << "Can't open " << file << " file for output.\n";
    		exit(EXIT_FAILURE);
    	}
    	cout << "Enter guest names (enter a blank line to quit):\n";
    	string name;
    	while (getline(cin, name) && name.size() > 0)
    	{
    		fout << name << endl;
    	}
    	fout.close();
    	// show revised file
    	fin.clear(); // not necessary for some compilers
    	fin.open(file);
    	if (fin.is_open())
    	{
    		cout << "Here are the new contents of the "
    			<< file << " file:\n";
    		while (fin.get(ch))
    			cout << ch;
    		fin.close();
    	}
    
    	return 0;
    }
    

    7.2 运行结果

    向文件追加内容*********************************************************************
    Here are the current contents of the guests.txt file:
    Jasmine
    lili
    bobo
    booooo
    boly
    Enter guest names (enter a blank line to quit):
    mama
    baba
    
    Here are the new contents of the guests.txt file:
    Jasmine
    lili
    bobo
    booooo
    boly
    mama
    baba
    

    8 二进制文件

    8.1 二进制文件与文本文件

    8.1.1 文本文件优缺点

    优点:

    • 易于阅读,可以使用文本编辑器或word阅读或修改文本文件
    • 文本文件在计算机之间容易传输

    缺点:如果将数字存储为文本格式的话,需要<<插入操作符将数字转换为字符才可存储到txt文件中。

    8.1.2 二进制格式文件优缺点

    优点:

    • 二进制格式对于数字来说更精确,因为它存储的是值的内部表示,因此不会有转换误差和舍入误差
    • 以二进制格式保存数据速度更快
    • 二进制格式占用空间更小

    缺点:二进制格式在计算机之间传输可能存在问题,因为不同计算机的内部存储格式可能不一样;这种情况下需要编写一个程序将一种数据格式转换为另一种数据格式。

    8.1.3 存储格式与文件格式

    使用二进制文件模式时,程序将数据从内存传输给文件(反之亦然)时,将不会发生任何隐藏的转换。

    Windows文本文件,使用回车和换行表示换行符;

    Mscintosh文本文件,使用回车表示换行符;

    UNIX和Linux文本文件,使用换行表示换行符;

    C++从UNIX发展而来,使用换行表示换行符;

    Windows C++程序在写文本文件时,自动将C++换行符转换为回车和换行;在读取文本文件时,将回车和换行转换为C++换行符。

    对于二进制数据,如果使用文本格式文件存储,可能会出现问题,double值中间的字节可能与换行符的ASCII码有相同的位模式;另外,文件尾的检测也存在区别;因此以二进制格式保存数据时,应使用二进制文件模式。

    8.2 C++实例

    8.2.1 代码

    /*
    Project name :			_26File
    Last modified Date:		2022年4月30日11点39分
    Last Version:			V1.0
    Descriptions:			二进制文件存储
    */
    
    #include <iostream>
    #include <fstream> // for file I/O,这个头文件包含了iostream头文件,所以此处可以不显示包含iostream头文件
    #include <cstdlib> // support for exit()
    #include <string>
    #include <iomanip>
    const int SIZE = 60;
    
    //用于二进制文件存储
    inline void eatline() { while (std::cin.get() != '\n') continue; }
    struct planet
    {
    	char name[20]; // name of planet
    	double population; // its population
    	double g; // its acceleration of gravity
    };
    
    int main()
    {
    	using namespace std;
    	cout << "二进制文件存储*******************************************************************" << endl;
    	char file[30] = "planets.dat";
    	planet pl;
    	cout << fixed << right;
    	// show initial contents
    	ifstream fin;
    	fin.open(file, ios_base::in | ios_base::binary); // binary file
    	//NOTE: some systems don't accept the ios_base::binary mode
    	if (fin.is_open())
    	{
    		cout << "Here are the current contents of the "
    			<< file << " file:\n";
    		while (fin.read((char*)&pl, sizeof pl))
    		{
    			cout << setw(20) << pl.name << ": "
    				<< setprecision(0) << setw(12) << pl.population
    				<< setprecision(2) << setw(6) << pl.g << endl;
    		}
    		fin.close();
    	}
    	// add new data
    	ofstream fout1(file, ios_base::out | ios_base::app | ios_base::binary);
    	//NOTE: some systems don't accept the ios::binary mode
    	if (!fout1.is_open())
    	{
    		cerr << "Can't open " << file << " file for output:\n";
    		exit(EXIT_FAILURE);
    	}
    	cout << "Enter planet name (enter a blank line to quit):\n";
    	cin.get(pl.name, 20);
    	while (pl.name[0] != '\0')
    	{
    		eatline();
    		cout << "Enter planetary population: ";
    		cin >> pl.population;
    		cout << "Enter planet's acceleration of gravity: ";
    		cin >> pl.g;
    		eatline();
    		fout1.write((char*)&pl, sizeof pl);
    		cout << "Enter planet name (enter a blank line to quit):\n";
    		cin.get(pl.name, 20);
    	}
    	fout1.close();
    	// show revised file
    	fin.clear(); // not required for some implementations, but won't hurt
    	fin.open(file, ios_base::in | ios_base::binary);
    	if (fin.is_open())
    	{
    		cout << "Here are the new contents of the "
    			<< file << " file:\n";
    		while (fin.read((char*)&pl, sizeof pl))
    		{
    			cout << setw(20) << pl.name << ": "
    				<< setprecision(0) << setw(12) << pl.population
    				<< setprecision(2) << setw(6) << pl.g << endl;
    		}
    		fin.close();
    	}
    
    	return 0;
    }
    

    8.2.2 运行结果

    二进制文件存储*******************************************************************
    Here are the current contents of the planets.dat file:
                   earth:          70.  9.98
    Enter planet name (enter a blank line to quit):
    viras
    Enter planetary population: 20
    Enter planet's acceleration of gravity: 6.77
    Enter planet name (enter a blank line to quit):
    
    Here are the new contents of the planets.dat file:
                   earth:          70.  9.98
                   viras:          20.  6.77
    
    D:\Prj\_C++Self\_26File\Debug\_26File.exe (进程 5992)已退出,代码为 0。
    要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
    按任意键关闭此窗口. . .
    

    9 随机存取

    9.1 简介

    随机存取指的是直接移动到文件的任何位置;常用于数据库文件,程序维护一个独立的索引文件,该文件指出数据在主数据文件中的位置。如果文件由长度相同的记录组成,这种方法实现起来最简单;每条记录表示一组相关的数据。

    9.2 随机位置输入输出实例–修改记录

    9.2.1 代码

    /*
    Project name :			_26File
    Last modified Date:		2022年4月30日21点49分
    Last Version:			V1.0
    Descriptions:			随机位置输入输出实例
    */
    
    #include <iostream>
    #include <fstream> // for file I/O,这个头文件包含了iostream头文件,所以此处可以不显示包含iostream头文件
    #include <cstdlib> // support for exit()
    #include <string>
    #include <iomanip>
    const int SIZE = 60;
    const int LIM = 20;
    
    //用于二进制文件存储
    inline void eatline() { while (std::cin.get() != '\n') continue; }
    struct planet
    {
    	char name[LIM]; // name of planet
    	double population; // its population
    	double g; // its acceleration of gravity
    };
    
    int main()
    {
    	using namespace std;
    	cout << "随机位置输入输出文件*********************************************************" << endl;
    	const char* file = "planets.dat";
    	planet pl;
    	cout << fixed;
    	// show initial contents
    	fstream finout; // read and write streams
    	finout.open(file,ios_base::in | ios_base::out | ios_base::binary);//输入输出模式打开
    	//NOTE: Some Unix systems require omitting | ios::binary
    	int ct = 0;
    	if (finout.is_open())
    	{
    		finout.seekg(0); // go to beginning
    		cout << "Here are the current contents of the " << file << " file:\n";
    		while (finout.read((char*)&pl, sizeof pl))
    		{
    			cout << ct++ << ": " << setw(LIM) << pl.name << ": "
    				<< setprecision(0) << setw(12) << pl.population
    				<< setprecision(2) << setw(6) << pl.g << endl;
    		}
    		if (finout.eof())
    			finout.clear(); // clear eof flag
    		else
    		{
    			cerr << "Error in reading " << file << ".\n";
    			exit(EXIT_FAILURE);
    		}
    	}
    	else
    	{
    		cerr << file << " could not be opened -- bye.\n";
    		exit(EXIT_FAILURE);
    	}
    	// change a record
    	cout << "Enter the record number you wish to change: ";
    	long rec;
    	cin >> rec;
    	eatline(); // get rid of newline
    	if (rec < 0 || rec >= ct)
    	{
    		cerr << "Invalid record number -- bye\n";
    		exit(EXIT_FAILURE);
    	}
    	streampos place = rec * sizeof pl; // convert to streampos type
    	finout.seekg(place); // random access 随机访问到指定位置
    	if (finout.fail())
    	{
    		cerr << "Error on attempted seek\n";
    		exit(EXIT_FAILURE);
    	}
    	finout.read((char*)&pl, sizeof pl);
    	cout << "Your selection:\n";
    	cout << rec << ": " << setw(LIM) << pl.name << ": "
    		<< setprecision(0) << setw(12) << pl.population
    		<< setprecision(2) << setw(6) << pl.g << endl;
    	if (finout.eof())
    		finout.clear(); // clear eof flag
    	cout << "Enter planet name: ";
    	cin.get(pl.name, LIM);
    	eatline();
    	cout << "Enter planetary population: ";
    	cin >> pl.population;
    	cout << "Enter planet's acceleration of gravity: ";
    	cin >> pl.g;
    	finout.seekp(place); // go back
    	finout.write((char*)&pl, sizeof pl) << flush;
    	if (finout.fail())
    	{
    		cerr << "Error on attempted write\n";
    		exit(EXIT_FAILURE);
    	}
    	// show revised file
    	ct = 0;
    	finout.seekg(0); // go to beginning of file
    	cout << "Here are the new contents of the " << file << " file:\n";
    	while (finout.read((char*)&pl, sizeof pl))
    	{
    		cout << ct++ << ": " << setw(LIM) << pl.name << ": "
    			<< setprecision(0) << setw(12) << pl.population
    			<< setprecision(2) << setw(6) << pl.g << endl;
    	}
    	finout.close();
    
    	return 0;
    }
    

    9.2.2 运行结果

    随机位置输入输出文件*********************************************************
    Here are the current contents of the planets.dat file:
    0:                earth:           70  9.98
    1:                 Boly:            4  9.99
    2:                earth:           80  9.98
    Enter the record number you wish to change: 2
    Your selection:
    2:                earth:           80  9.98
    Enter planet name: Jasminely
    Enter planetary population: 4
    Enter planet's acceleration of gravity: 9.99
    Here are the new contents of the planets.dat file:
    0:                earth:           70  9.98
    1:                 Boly:            4  9.99
    2:            Jasminely:            4  9.99
    
    D:\Prj\_C++Self\_26File\Debug\_26File.exe (进程 16340)已退出,代码为 0。
    要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
    按任意键关闭此窗口. . .
    

    10 生成不同的文件名

    10.1 简介

    //tmpnam函数生成临时文件名并将其放置到pszName指向的存储空间中;定义在头文件cstdio中的常量L_tmpnam限制了文件名包含的字符数,TMP_MAX限制了在生成文件名不重复的条件下tmpnam()函数可被调用的最多次数。
    char* tmpnam( char* pszName );
    

    10.2 代码

    #include <cstdio>
    #include <iostream>
    int main()
    {
    	using namespace std;
    	cout << "This system can generate up to " << TMP_MAX
    		<< " temporary names of up to " << L_tmpnam
    		<< " characters.\n";
    	char pszName[L_tmpnam] = { '\0' };
    	cout << "Here are ten names:\n";
    	for (int i = 0; 10 > i; i++)
    	{
    		tmpnam(pszName);
    		cout << pszName << endl;
    	}
    	return 0;
    }
    

    10.3 运行结果

    每次运行的结果不同。

    生成不同的文件名*************************************************************
    This system can generate up to 2147483647 temporary names of up to 260 characters.
    Here are ten names:
    C:\Users\15495\AppData\Local\Temp\u994.0
    C:\Users\15495\AppData\Local\Temp\u994.1
    C:\Users\15495\AppData\Local\Temp\u994.2
    C:\Users\15495\AppData\Local\Temp\u994.3
    C:\Users\15495\AppData\Local\Temp\u994.4
    C:\Users\15495\AppData\Local\Temp\u994.5
    C:\Users\15495\AppData\Local\Temp\u994.6
    C:\Users\15495\AppData\Local\Temp\u994.7
    C:\Users\15495\AppData\Local\Temp\u994.8
    C:\Users\15495\AppData\Local\Temp\u994.9
    
    D:\Prj\_C++Self\_26File\Debug\_26File.exe (进程 11992)已退出,代码为 0。
    要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
    按任意键关闭此窗口. . .
    
    展开全文
  • C++输入输出流

    千次阅读 2022-03-31 10:56:46
    C++用继承方法建立了I/O类库,输入输出过程(input/output)称为,输入是指将数据从输入设备保存到内存的过程,输出是指从内存传输到输入设备的过程

    C++用继承方法建立了I/O流类库,输入输出过程(input/output)称为流,输入是指将数据从输入设备保存到内存的过程,输出是指从内存传输到输入设备的过程

    1.输入输出流对象

    1.1 标准流对象

    键盘是标准输入流设备,屏幕是标准输出流设备 :cin(istream的对象,从键盘输入数据到内存中)cout(ostream,从内存输出数据到屏幕上),cerr和 clog是ostream的对象,处理错误信息标准输出

    1.2 文件流对象

    对文件进行输入(读)输出(写)操作

    定义文件流对象,通过文件流的成员函数进行打开操作

    void open(const char*filename,mode) mode为打开方式

    ifstream outfile;//以输入方式打开文件

    outfile.open("file.txt")

    mode
    ios::in(ifstream默认打开方式)以输入方式打开文件,,该文件必须存在
    ios::out(ofstream)以输出方式打开文件,
    ios::app以追加方式打开文件,所有输出附加在文件末尾,指针指向EOF
    ios::ate文件指针指向EOF
    ios::binary以二进制方式(通常为纯数值文件)打开文件
    ios::trunc如果文件存在,先删除文件内容

    2.输入输出流对象的成员函数

    2.1运算符重载<<和>>

    <<插入运算符

    a. 标准输出 cout<<endl; 即 cout.operator<<(endl);

    b.文件输出 将内存中的数据写入文件中

    fstream outfile("file.txt",ios::out)

    outfile<<x<<end'<<y<<endl<<z;

    outfile.close();

    //先在程序的目录下生成file.txt的文件,将x,y,z对应内存中的数据写入文件中,关闭文件

    >>提取运算符

    a.标准输入 从键盘提取数据到内存

    cin>>a>>b>>c;

    b. 文件输入 >>将文件中的数据读取到内存中

    fstream infile("file.txt",ios::in)

    infile>>a>>b>>c;

    infile.close();//将上建立的file.txt文件,数据依次读取到变量 a,b c中

    2.2 常见输入流的成员函数

    2.2.1 get() 从输入设备获取单个字符

    a. 标准输入 get()

    char ch;
    while(ch=cin.get()!='\n')//输入回车符时循环结束
    { cout<<ch;
    }

    b. 文件输入

    get()

    fstream outfile("file.txt",ios::out);
    outfile<<"Visual Studio“;
    outfile.close();
    fstream infile("file.txt",ios::in)
    char ch;
    while(ch=infile.get()!=EOF)
    cout<<ch;

    get(ch)//字符型变量作为参数,函数调用时提取一个字符并将其写入该变量的内存地址中,读取失败(遇到文件结束符 EOF),返回为假

    while(infile.get(ch))
    cout<<ch;

    2.2.2 getline() 从输入设备中读取一个字符串

    参数 in.getline(字符数组或字符型指针,字符个数n,终止标识符)

    n=n-1+'\0'

    a. 标准输入 可读取含空白字符的字符串 直到达到个数或遇到终止标识符

    while(cin.getline(s,80))
    //ctrl+z(eof)结束循环
    

    b. 文本文件输入 读取文件并输出到数组中

    fstream outfile;
    outfile("file.txt",ios::out);
    outfile<<"Visual Studio"<<endl
    <<"c++"<<endl
    <<"wang"<<endl;
    outfile.close();
    fstream infile;
    infile("file.txt,ios::in);
    char ch;
    int len,minlen=0;
    char ch[30],s[20];
    while(infile.getline(ch,sizeof(ch))
    {
    len=(int)strlen(ch);
    if(minlen>len)
    strcpy(s,ch);
    }
    

    2.2.3 read() 输入流对象可调用此函数实现从键盘输入制定个数的多个字符的操作

    in.read(字符型指针,字符个数n) 可读取空白字符,不会自动添加字符结束符'\0'

    a. 标准输入

    char s[20];
    cin.read(s,12);
    for(int i=0;i<12;i++)
    cout<<s[i];

    b.二进制文件输入

    fstream outfile("file.dat",ios::binary|ios::out);
    for(int a=1;a<=10;a++)
    outfile.write((char*)&a,sizeof(a));
    outfile.close();
    fstream infile("file.dat".ios::binary|ios::in);
    while(infile.read((char*)&a,sizeof(a)))
    cout<<a<<' ';
    infile.close();

    read函数要求第一个参数为字符型指针,(char*)&a 强制将变量a的地址转换为字符型指针

     2.3 常见输出流的成员函数

    2.3.1 put()函数 输出单个字符的成员函数

    a.标准输出//以引用方式返回调用该函数所使用的输出流对象,支持连续调用

    char ch='a';
    cout.put(ch);
    cout.put('b').put('c')<<endl;
    

    b.文本文件输出

    char ch='a';
    fstream outfile("file.txt",ios::out)
    outfile.put(ch);
    outfile.close();

    2.3.2 write()函数  用于输出多个字符的成员函数write(),输出流对象可调用此函数向输出设备输出多个指定个数的多个字符的操作

    a. 标准输出流 write(字符型指针,字节数n)

    char*ch="一带一路 协同共进";
    cout.write(ch,8).put('\n');
    cout.write(ch,strlen(ch))<<endl;

    b. 二进制文件输出

    int a=12345;
    fstream outasc("file.txt",ios::out);
    fstream outbin("file.dat",ios::binary|ios::in);
    outasc<<a;
    outbin.write((char*)&a,sizeof(a));
    outbin.close();
    outasc.close();
    //file.txt 文件内容12345,5个字节
    file.dat 文件内容 39300000 四个字节 二进制数对应为0x00003039
    #include<iostream>
    #include<fstream>
    using namespace std;
    struct Student//将三名学生的信息存入二进制文件后,再读到结构体数组中,输入到屏幕上
    {
    char num[10];
    char name[20];
    int score;
    };
    int main()
    {
    Student stu[]={
    {"101","张三”,89},
    {"102","李四",91},
    {"103","王五",85}
    };
    fstream outfile("info.dat",ios::binary|ios::out);
    for(int i=0;i<3;i++)
    outfile.write((char*)&stu[i],sizeof(stu[i]);
    outfile.close();
    fstream infile("info.dat",ios::binary|ios::in);
    for(int i=0;i<3;i++)
    infile.read((char*)&stu.[i],sizeof(stu[i]);
    cout<<stu[i].num<<stu[i].name<<stu[i].score<<endl;
    infile.close();
    return 0;
    }
    

    展开全文
  • 文章目录一、C语言的输入输出二、什么是三、C++的IO1.概览2.标准IO(1)cin、cout、cerr、clog(2)cin、cout与scanf、printf(3)输入输出重载(4)getline(5)循环输入2.文件流(1)ifstream、ofstream感谢...
  • C++输入流和输出流(超级详细)

    千次阅读 2022-02-13 09:31:32
    C++输入流和输出流(超级详细) C++ 又可以称为“带类的 C”,即可以理解为 C++ 是 C 语言的基础上增加了面向对象(类和对象)。在此基础上,学过 C 语言的读者应该知道,它有一整套完成数据读写(I/O)的解决方案:...
  • C++--标准输入输出流

    2022-04-14 17:13:05
    4.C++有一个新的输入输出流库(头文件iostream)将输入输出看成一个流,并用输出运算符 << 和输入运算符 >> 对数据(变量和常量进行输入输出)。 其中 cout 和 cin 分别代表标准输出流对象(屏幕窗口)和标准...
  • C++文件输入输出流fstream的用法

    千次阅读 2021-03-24 19:52:40
    C++的IO类中定义了三个文件读写fstream、ifstream以及ofstream,它们都继承于相同的父类istream,通过不同的实现以实现不同的文件流操作。 三者的区别为: ifstream:从文件读取数据 ofstream:从文件写入数据 ...
  • JAVA开发与应用输入输出流文件.ppt
  • 一文搞懂C++输入输出流,从此不再陌生。 cin.get(),cout.put(). cin.getline(),cout.write()讲解
  • C++文件输入输出流及标准I/O流类知识总结

    万次阅读 多人点赞 2018-10-13 23:42:06
    在学习使用C++进行STL模型文件的读写与显示时,遇到了一些文件读取的问题...C++所有的输入输出流(I/O)都是基于stream流类,包括iostream,fstream,stringstream等,其对象称为流对象,其之间的相互关系如下: ...
  • C++文件操作(输入输出流

    万次阅读 多人点赞 2018-09-26 20:37:15
    到目前为止,我们已经使用了 iostream 标准库,它提供了 cin 和 cout 方法分别用于从标准输入读取和向标准输出写入。 本教程介绍如何从文件读取和向文件写入。这就需要用到 C++ 中另一个标准库 fstream,它...
  • C++——输入输出

    千次阅读 2022-02-04 18:36:35
    的基本认识和与输入输出形成的体系以及C++中一些输入输出方法的介绍
  • C++ 输入输出流

    千次阅读 2021-04-06 20:08:31
    C++ 输入输出流 输入输出流基本概念 与输入输出流操作相关的类:类的继承关系从上往下如下图所示 istream:用于输入的流类,cin 是该类的对象 ostream:用于输出的流类,cout cerr clog 是该类的对象 ifstream:...
  • 至此你不需要配置任何其他东西,就可以在本地利用输入输出文件安心调试你的代码,调试后直接拷贝,提交到各大OJ平台即可 该代码真的超级好用 例如: #include using namespace std; typedef long long ll; int main...
  • 文件流类和文件流对象文件流是以外存文件输入输出对象的数据。输出文件流 内存-&gt;外存输入文件流 外存-&gt;内存 文件流的名称 的作用 ifstream类 从istream类派生的,用来支持从磁盘文件的...
  • fstream头文件定义了用于文件输入的类ifstream和文件输出的类ofstream 2.写文件 1)创建一个ofstream对象来管理输出流 2)将该对象与文件关联起来 3)使用cout方式使用该对象,唯一区别是输出将进入文件,而不是屏幕。...
  • C++输入输出流文件流操作笔记

    千次阅读 2021-05-19 08:52:37
    stdiostream用于混合使用C和C + +的I/O机制时,例如想将C程序转变为C++程序2、类继承关系ios是抽象基类,由它派生出istream类和ostream类, iostream类支持输入输出操作,iostream类是从istream类和ostream类通过...
  • C++实验9 输入输出流

    千次阅读 2019-06-16 09:21:28
    所使用的开发工具及环境:PC机一套 Visual Studio 2010 实验要求: 1.硬件基本配置:Intel PentiumIII以上级别的CPU,大于64MB的内存。 2.软件要求:Window 2000操作系统...1、深入理解C++输入输出的含义与其实现...
  • C++--输入输出流

    2021-04-21 20:35:17
    输入输出流2.1 流2.2 C++标准IO流2.3 C++文件IO流3. stringstream 1. 输入输出 程序的输入:从输入文件将数据传送给程序; 程序的输出:从程序将数据传送给输出文件; C++输入输出包括: 对系统指定标准设备的...
  • C++文件的写与读(输入输出流

    千次阅读 2022-04-25 23:56:39
    C++中对文件操作需要包含头文件<fstream> 文件类型分为两种: 1.文本文件 2.二进制文件 操作文件的三大类: 1.ofstream:写操作 2.ifstream:读操作 3.fstream:读写操作 一、写文件 五大步骤 1....
  • C++基础 输入输出流及常用头文件

    千次阅读 2019-06-30 21:23:45
    输入输出流 scanf 和 printf 格式化输入格式化输出:需要对应格式,用指针操作,没有类型安全机制,数据量大时效率高 cin 和 cout 流输入流输出:读取是数据流,而不是具体的数据,自动判断变量类型,不需要指定。...
  • c++文件输入输出

    千次阅读 2022-03-14 09:58:45
    基于文件IO 头文件 ofstream : 写文件 ifstream : 读文件 fstream : 读写文件 using namespace std; //打开文件 std::ifstream fin("xxx.txt"); //std::ifstream fin; //fin.open("xxx.txt"); std::ofstream ...
  • C++实现简单的文件输入输出

    千次阅读 2022-03-18 20:10:09
    这样的输入输出有时候不能满足要求,这个时候需要我们读写文件来获得、存储我们的数据。 读文件或者写文件 大致分为5个步骤 包含头文件(fstream)-创建-打开文件,使文件建立联系-读写操作-关闭文件 的...
  • C++实验: 输入输出流

    2020-08-27 10:56:42
    C++实验: 输入输出流 1. 实验目的 (1) 深入理解C++的输入输出的含义与其实验方法。 (2) 掌握标准输入输出流的应用,包括格式输入输出。 (3) 掌握对文件的输入输出操作。 2. 实验内容 (1) 编写程序判断...
  • C++学习笔记】C++输入输出流

    千次阅读 2021-08-04 20:47:16
    文章目录C++输入流和输出流(超级详细)C++输入流和输出流C++ cout.put():输出单个字符C++ cout.write():输出字符串C++ cout.tellp()和cout.seekp()方法详解C++ tellp()成员方法C++ seekp()成员方法C++ cout格式化...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 100,637
精华内容 40,254
关键字:

c++文件输入输出流

c++ 订阅