C++基础知识(6)IO库

文章详细介绍了C++中的IO库,包括iostream、fstream和sstream的基本用法。iostream用于标准输入输出,如cin和cout;fstream处理文件输入输出,如ifstream和ofstream;sstream则允许在字符串中进行输入输出操作。同时,文章强调了IO对象的状态管理和错误处理,如使用bad()、fail()和clear()等函数检查和恢复错误状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. IO库的组成部分

IO就是input,output的缩写,也就是输入输出功能。

  1. C++定义了ios这个基类来定义输入输出功能,而C++IO库的所有的类都继承自这个类。
  2. istream,ostream直接继承自ios类:
    (1)ostream类定义了从内存到输出设备的功能,我们常用的cout就是ostream类的对象。
    (2)istream类定义了从输入设备到内存的功能,我们常用的cin就是istream类的对象。
    (3)iostream文件定义了ostream和istream类的对象,也就是cout和cin,我们平时引用头文件就是在做这个操作。
  3. ifstream,ofstream类分别继承自istream类和ostream类:
    (1)ifstream类定义了从磁盘写入内存的功能,因为istream重载了<<运算符,所以ifstream也继承了<<的重载。注意:除了=运算符,其他运算符都是可以被继承的。
    (2)ofstream类定义了从内存写入磁盘的功能。
    (3)fstream文件引入了ifstream和ofstream,所以我们引入fstream文件就能进行文件流功能。

注意:磁盘与输入输出设备的交互只能通过内存来中转。

  1. istringstream,ostringstream类分别继承自istream类和ostream类:
    (1)istringstream类定义了从指定字符串到特定内存的功能。
    (2)ostringstream类定义了从特定内存到指定字符串的功能。
    (3)sstream文件引入了istringstream和ostringstream,我们可以使用字符串与内存直接交互数据的功能。

因此我们主要引入iostream,fstream,sstream头文件进行操作。

2. IO库的注意事项

IO对象无法使用拷贝构造和赋值运算符,所以我们使用流对象无法使用值传递,一般使用引用进行传递

#include<iostream>
#include<fstream>
#include<sstream>
void testStreamMain()
{
    std::istream myCin(std::cin); // 错误,无法进行拷贝构造
}
class Test
{
    friend std::ostream& operator<< (std::ostream& os, const Test& test); // 我们只能使用引用传递
};

IO对象的状态

  1. IO操作是非常容易出现错误的操作的,比如我们使用cin向int对象中输入一个字符串,会使cin这个对象出现错误。所以当我们使用IO对象时都应该判断IO对象的状态。
  2. IO库定义了iostate类型,可以完整的表示io对象当前的状态,使用不同位置1来标记错误。即使用bad()fail()来检测出错误就可以了。
  3. iostate状态的类型
  • badbit状态:系统级错误,一旦badbit置1,则流对象无法使用,bad()被置1返回true。
  • failbit状态:可恢复的错误,当badbit置1时,failbit也会被置1,fail()被置1返回true。
  • eofbit状态:当到达文件结束位置时,eofbit和failbit都会被置1。eof()被置1返回true。
  • goodbit状态:表示流对象没有任何错误,good()在所有位都未被置1返回true。
  1. 流对象的管理
  • rdstate()函数:返回一个iostate值,对应当前流状态。
  • setstate(flag)函数:将对象流设置为想要的状态。
  • clear()函数:将所有状态位置0。
  • ignore()函数:提取字符串并丢弃。
/*
* 标准的IO书写格式
**/
#include<iostream>
void testStreamMain()
{
    int i = 10;
    while (std::cin >> i, !std::cin.eof())
    {
        if (std::cin.bad()) // 是否出现系统级错误
        {
            throw std::runtime_error("cin is corrupted");
        }
        if (std::cin.fail()) // 是否出现可恢复错误
        {
            // 清空状态位
            std::cin.clear();
            // 清空缓冲区,清空字符串,直到'\n'为止
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
            std::cout << "data format error, please try again" << std::endl;
            continue;
        }
        std::cout << i << std::endl;
    }
    std::cout << "process complete" << std::endl;
}

3. iostream

3.1 geline

getline按行接收数据,因为存储在string对象中,所以不容易出现格式错误,当仍可能出现系统级错误。

#include<string>
std::getline(cin, inputLine); // 第一个参数为cin,就是正在读取的输入流,第二个参数为inputLine是接收流读取内容的变量

注意:使用getline函数一定要包含string头文件。

#include<iostream>
#include<string>
void testStreamMain()
{
    std::string str;
    while (std::getline(std::cin, str), !std::cin.eof())
    {
        if (std::cin.bad()) // 是否出现系统级错误
        {
            throw std::runtime_error("cin is corrupted");
        }
        std::cout << str << std::endl;
    }
    std::cout << "process complete" << std::endl;
}

3.2 get

#include<iostream>
std::cin.get(c); // get字符并存入c中
std::cin.getline(str, count); // getline一行20个字符,存入str中,以'/n'终止

get是以字符的格式进行接收,与getline类似。

#include<iostream>
void testStreamMain()
{
    char c;
    while (std::cin.get(c), !std::cin.eof())
    {
        if (std::cin.bad()) // 是否出现系统级错误
        {
            throw std::runtime_error("cin is corrupted");
        }
        std::cout << c << std::endl;
    }
    std::cout << "process complete" << std::endl;
}

4. fstream

IO库没有默认给出ifstream和ofstream类的对象,因此需要我们自己定义。

#include<iostream>
#include<string>
#include<fstream>
/*
* 标准的文件流书写格式
* 功能:输入文件名,打开相应文件,并输出文件的内容
**/
void testStreamMain()
{
    std::string fileName;
    std::string fileContent;
    while (std::cin >> fileName, !std::cin.eof())
    {
        if (std::cin.bad()) // string存储,只需要判断bad()
        {
            throw std::runtime_error("cin is corrupted");
        }
        std::ifstream ifs(fileName); // 定义ifstream,一个文件流对象,一定要绑定一个文件
        if (ifs.is_open())
        {
            while (std::getline(ifs, fileContent))
            {
                std::cout << fileContent << std::endl;
            }
            if (ifs.bad())
            {
                std::cout << "ifs is corrupted" << std::endl;
            }
            ifs.close(); // 一定要关闭!因为文件存在操作系统内核区,打开了不关闭很麻烦!
        }
        else
        {
            ifs.clear();
            ifs.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            std::cout << "file not exist, please try again" << std::endl;
            continue; // 循环继续
        }
    }
    std::cout << "process complete" << std::endl;
}

文件模式
(1)in:以读的方式打开,ifstream的默认模式。
(2)out:以写的方式打开,ofstream的默认模式。
(3)app:在进行写操作时定位到文件末尾。
(4)ate:打开文件后定位到文件末尾。
(5)trunc:截断文件(把文件已有的全部删除,重新开始写),ofstream的默认写文件方式。
(6)binary:以二进制的方式打开文件。

std::ofstream ofs("test.txt", std::ios::app  | std::ios::trunc); // 追加模式与截断模式,注意文件模式也是按位操作
if (ofs.is_open())
{
    ofs << "Hello" << std::endl;
    ofs.close();
}

5. sstream

sstream流可以向string对象写入数据,也可以从string对象读取数据,与文件操作类似,string流默认包含一个string对象。

  1. 对于stringstream,也需要我们自己定义流对象。
  2. 构造函数指定对应的string,如果是默认的构造函数,是一个空的字符串。
  3. str()函数:返回流对应的字符串的值(不是引用)。
  4. str(“XXX”)函数:表示原有的字符串被销毁,存储新的“XXX”,返回void。
void testStreamMain()
{
    std::string str("Hello");
    std::istringstream isstream(str);
    isstream.str();
}
  1. string流的类型转化

string流进行string与其他类型的转化,这也是string流对象最重要的功能。

#include<iostream>
#include<string>
#include<sstream>
/*
* 功能:通过流将string转换为int
**/
void testStringToInt()
{
    std::string str("12");
    std::stringstream strStream(str);
    int i = 0;
    strStream >> i; // 直接将string流对象流出,完成格式转化
    if (strStream.bad())
    {
        throw std::runtime_error("strStream is corrupted");
    }
    else if (strStream.fail())
    {
        strStream.clear();
        strStream.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        std::cout << "format error" << std::endl;
    }
    else
    {
        std::cout << i << std::endl;
    }
}
/*
* 功能:通过流将int转换为string
**/
void testIntToString()
{
    int i = 50;
    std::stringstream strStream;
    strStream << i << std::endl; // 直接将string流对象流入,完成格式转化
    if (strStream.bad())
    {
        throw std::runtime_error("strStream is corrupted");
    }
    else
    {
        std::cout << strStream.str() << std::endl;
    }
}
  1. 使用string流对空格分割的字符串进行切分。
void testStreamMain()
{
    std::string str("Hello Hello Hello");
    std::string outStr;
    std::stringstream strStream(str);
    while (strStream >> outStr)
    {
        std::cout << outStr << std::endl;
    }
    if (strStream.bad())
    {
        throw std::runtime_error("strStream is corrupted");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值