MSIPO技术圈 首页 IT技术 查看内容

C++基础之输入输出流(九)

2024-03-21

首先什么是流,流是一个字节序列,而程序的输入输出就发生在流中。如果字节流是从设备(如键盘)流向内存,那么就叫他输入流。如果字节流从内存流向设备(如显示屏),那么就叫做输出流。所以在我们判断是否是输出流还是输入流,只需要看文件是否是流向内存,还是从内存流出。

一.在C++中常用的数据流类型

1.标准设备的输入输出,即从键盘输入数据,输出到显示器屏幕上,这种输入输出简称标准I/O。

2.以外存的文件为对象进行输入输出,即从磁盘文件输入数据,数据输出到磁盘文件。这种输入输出简称文件I/O。

3.对内存中指定的空间进行输入输出。通常指定一个字符数组为存储空间。这种输入输出称为字符串输入输出,简称串I/O。

二.数据流中的缓冲区

缓冲区又称为缓存,他是内存空间的一部分,因为cpu的速度很快,而外设等输出设备的速度很慢,为解决快速CPU和慢速输出输入设备的速度不匹配问题,我们设置输入输出缓冲区。其中缓冲区的执行过程,比如我们从磁盘里取数据,然后把读出数据放入缓冲区,计算机需要数据时直接从缓冲区读取,等到缓冲区的数据被CPU读取结束,然后再从磁盘读数据放缓冲区。这样就可以大大减少磁盘的读写次数,而CPU读取缓冲区的数据大大快于从磁盘中读取数据。这样缓冲区就可以加快计算机的运行速率。

缓冲区的类型

缓冲区分为三种类型:全缓冲,行缓冲,和不带缓冲。

1.全缓冲:在这种情况下,当填满标准I/O缓存后才进行实际的I/O操作。全缓冲的典型代表就是磁盘文件的读写。

2.行缓冲:在这种情况下,当输入输出遇到换行符时,执行真正的I/O操作。这时我们输入的字符先存放在缓冲区,等按下回车键换行时才会进行实际的I/O操作,典型的代表就是键盘输入数据。

3.不带缓冲:不进行缓冲,典型代表是标准出错cerr/stderr。因为出错信息要直接显示出来,不要在进行缓冲。

刷新输出缓冲区

输出缓冲区内容刷新的意思是:输出缓冲区的内容写到输出设备或文件中。

有以下几种情况刷新:

  1. 程序正常结束(有一个收尾操作就是清空缓冲区);
  2. 缓冲区满时会自动刷新缓冲区;
  3. 使用操纵符显示刷新输出缓冲区,如endl,flush
  4. 使用unitbuf操纵符设置流的内部状态;
  5. 输入流与输出流相关联,此时在读输入流时将刷新与其关联的输出流的输出缓冲区。

三.常用输入输出流类

类名                                                作用                                                        头文件

istream                                        通用输入流                                                iostream

ostream                                       通用输出流                                                

iostream                                      通用输入输出流                                        

ifstream                                       文件输入流                                                fstream

ofstream                                      文件输出流                        

fstream                                        文件输入输出流                

istringstream                                字符串输入流                                            sstream

ostringstream                               字符串输出流                                        

stringstream                                字符串输入输出流        

流的状态

  1. badbit表示发生系统级的错误,如不可恢复的读写错误。通常情况下一旦badbit被置位,流就无法在使用了。
  2. failbit表示发生可恢复的错误,如期望读取一个整数,却读出一个字符等错误。这种问题通常是可以修改恢复的,流还可以继续被使用。
  3. eofbit当文件到达末尾eof和fail都会被置位。
  4. goodbit表示流未发生错误。

管理流的状态

bool bad() const;        //若流的badbit置位,则返回true;否则返回false

bool fail() const;        //若流的failbit或badbit置位,则返回true;

bool eof() const;        //若流的eofbit置位,则返回true;

bool good() const;        //若流处于有效状态,则返回true;

//clear的无参版本会复位流的标志位重置流的状态

void clear(std::ios_base::iostate state = std::ios_base::goodbit);

流的通用操作

常见问题

文件游标

#include <iostream>
#include <fstream>

using std ::ifstream;
using std::cin;
using std::cout;
using std::string;
using std::endl;
using std::ofstream;

void printStreamStatus()
{
    cout<<"cin.badbit = "<<cin.bad()<<endl
    <<"cin.failbit = "<<cin.fail()<<endl
    <<"cin.eofbit = "<<cin.eof()<<endl
    <<"cin.goodbit = "<<cin.good()<<endl;
}

void test4()
{
    fstream fs("test.txt");

    int number=0;
    for (int i = 0; i < 5; i++)
    {
        cin>>number;
        fs<<number<<" ";
    }
    
    for (int i = 0; i < 5; i++)
    {
         printStreamStatus();
        //游标
        fs>>number;
        cout<<number<<" "<<endl;
    }
    
    cout<<endl;
    
    fs.close();
}
int main()
{
    test4();
    return 0;
}

可以看出打印并不是我们预期输入的2 3 4 5 6,而文件中存入的确实是2 3 4 5 6但是打印的是6 6 6 6 6通过流的状态我们可以看出eof()和fail()标志位都被置1,而eof表示我们已经到达文件末尾了。所以这个程序的问题就是当我们输入数据时,文件的游标会跟随我们输入的一同移动一直指向最后一个位置。

void test4()
{
    string line;
    fstream fs("test.txt");

    int number=0;
    for (int i = 0; i < 5; i++)
    {
        cin>>number;
        fs<<number<<" ";
    }
    cout<<fs.tellp()<<endl;//获取游标位置
    fs.seekp(0);//设置游标绝对位置
    for (int i = 0; i < 5; i++)
    {
     
        //游标
        
        fs>>number;
        cout<<number<<" ";
    }
    
    cout<<endl;
    
    fs.close();
}

相关阅读

热门文章

    手机版|MSIPO技术圈 皖ICP备19022944号-2

    Copyright © 2024, msipo.com

    返回顶部