登录  | 立即注册

游客您好!登录后享受更多精彩

查看: 85|回复: 0

C++Primer学习笔记08.IO库

[复制链接]

44

主题

-24

回帖

30

积分

新手上路

积分
30
发表于 2025-1-5 12:11:02 | 显示全部楼层 |阅读模式

IO类

<div align="center"><h6>IO库类型和头文件</h6></div>

头文件 类型 说明
iostream istream、wistream 从流中读取<br>ostream、wostream 写到流中去<br>iostream、wiostream 可读可写 控制台输入输出流
fstream ifstream、wifstream 从文件中读取<br>ofstream、wofstream 写到文件中去 文件输入输出流
sstream istringstream、wistringstream 从 string 对象中读取<br>ostringstream、wostringstream 写到 string 对象中去<br>stringstream、wstringstream 对 string 对象进行读写 string 对象的输入输出

w 开头的表示支持 wchar_t 类型的数据。且三个头文件的接口基本一致。

IO对象无拷贝或赋值

ofstream out1, out2;
out1 = out2;                // 错误:不能对流对象赋值
ofstream print(ofstream);   // 错误:参数传递也是一种赋值的过程
out2 = print(out2);         // 错误:不能拷贝流对象

读写一个 IO 对象会改变其状态,因此传递和返回的引用不能是 const。

条件状态

IO 类所定义的一些函数和标志,可以帮助我们访问和操纵流的条件状态

<div align="center"><h6>IO库条件状态</h6></div>

状态 含义
strm::iostate strm 是一种 IO 类型。iostate 是一种机器相关的类型,提供了表达条件状态的完整功能
strm::badbit 用来指出流已奔溃
strm::failbit 用来指出 IO 操作失败
strm::eofbit 用来指出流到达了文件结束
strm::goodbit 用来指出流末处于错误状态。辞职保证未零
s.eof() 若流 s 的 eofbit 置位,则返回 true
s.fail() 若流 s 的 failbit ,则返回 true
s.bad() 若流 s 的 badbit 置位,则返回 true
s.good() 若流 s 处于有效状态,则返回 true
s.clear() 将流 s 中所有条件状态位复位,将流的状态设置为有效。返回 void。
s.clear(flags) 根据给定的 flags 标志位,将流 s 中对应条件状态复位。flags 的类型位 strm::iostate。返回 void。
s.setstate(flags) 根据给定的 flags 标志位,将流 s 中对应条件状态置位。flags 的类型位 strm::iostate。返回 void。
s.rdstate() 返回流 s 的当前条件状态,返回值类型为 strm::iostate
auto old_state = cin.rdstate();     // 记录当前状态
cin.clear();                        // 使 cin 有效
process_input(cin);                 // 使用 cin
cin.setstate(old_state);            // 还原状态

复位 failbit 和 badbit

cin.clear(cin.rdstate() & ~cin.failbit & ~cin.badbit);

缓冲区

通过 io 库处理的流可能会立即刷新出去,也可能为暂存到系统缓冲区,缓冲区满时在处理。C++ 的 endl 可以显示的刷新缓冲区。cin 和 cout 交替执行也会触发缓冲区的刷新。

<span style="color:red">如果程序崩溃,输出缓冲区不会被刷新</span>

文件输入输出

- -
fstream fstrm 创建一个未绑定文件的文件流
fstream fstrm(s) 创建一个文件里,并打开名为 s 的文件。构造函数都是 explicit 的,因此没有隐式转换
fstream fstrm(s, mode) 指定了打开的模式
fstrm.open(s) 打开名为 s 的文件
fstrm.close() 关闭与 fstrm 绑定的文件,返回 void
fstrm.is_open() 返回 bool,指出与 fstrm 关联的文件是否成功打开且未关闭

使用文件 IO 打开文件,并写入到另一个文件中去。

#include<iostream>
#include <fstream>

void testWrite() {
    std::ofstream fout("/home/xxx/cpp/primer/chapter08/helloc.txt");
    std::string str;
    std::cout << "请输入内容" << std::endl;
    while (std::cin >> str) {
        if (str == "886") {
            break;
        }
        fout << str << std::endl;

    }
    std::cout << "write over!" << std::endl;
}

void testRead() {
    std::ifstream fin("/home/xxx/cpp/primer/chapter08/helloc.txt");
    std::string line;
    if (fin.is_open()) {
        while (getline(fin, line)) std::cout << line << std::endl;
    }
}

int main() {
    testWrite();
    testRead();
}

close 方法时关闭当前当前关联的文件,关闭后就可以关联下一个文件了。

void testClose() {
    std::ifstream fin("/home/liujiawei/cpp/primer/chapter08/helloc.txt");
    std::string line;
    if (fin.is_open()) {
        while (getline(fin, line)) std::cout << line << std::endl;
    }
    fin.close();
    fin.open("/home/liujiawei/cpp/primer/chapter08/hello.txt");
    if (fin.is_open()) {
        while (getline(fin, line)) std::cout << line << std::endl;
    }
}

如果 open 成功,则 open 会设置流的状态,使得 good() 为 true。

一份正确的 IO 流代码应该是考虑了各种错误情况,确保文件可以正常输入、输出的。

文件模式

每个流都有一个关联的文件模式。

模式 说明
in 读模式
out 写模式,会丢弃现有数据。
app 追加写
ate 打开文件时定位到文件末尾
trunc 截断文件,把一个文件的尾部砍掉。
binary 二进制方式进行 IO,适用于非文本数据

每次调用 open 时都会确定文件模式,文件隐式地以 out 模式打开。通常情况下,out 模式意味着同时使用 trunc 模式。

string流

用 IO 的方式来处理 string。即内存 IO。istringstream 从 string 读取数据,ostringstream 向 string 写入数据,而头文件 stringstream 既可从 string 读数据也可向 string 写数据。

- -
sstream strm 声明对象,但是没绑定 string
sstream strm(s) 绑定了 string,构造方法都是 explicit 的
strm.str() 返回 strm 保存的 string 的拷贝
strm.str(s) 将 string s 拷贝到 strm 中,返回 void

istringsteam 和 ostringstream 的具体用处不是很明白,书中只简单说了下<u>"用于读写给定 string 的字符串流"</u>。

#include<iostream>
#include <sstream>
#include <vector>

struct PersonInfo {
    std::string name;
    std::vector<std::string> phones;
};

void testOS() {
    std::string line;
    std::ostringstream os;
    while (std::cin >> line) {
        if (line == "886") {
            break;
        }
        os << line;
    }
    std::cout << os.str() << std::endl;
}

void testIS() {
    std::string line, word;
    std::vector<PersonInfo> people;
    while (getline(std::cin, line)) {
        if (line == "886") break;
        PersonInfo info;
        /**
         * 将一个 istringstream 与刚刚读取的文本行进行绑定,
         * 这样就可以在此 istringstream 上使用输入运算符来读取当前记录中的每个元素。
         * 我们首先读取人名,随后用一个 while 循环读取此人的电话号码
         * */
        std::istringstream record(line);
        record >> info.name;
        while (record >> word)
            info.phones.push_back(word);
        people.push_back(info);
    }
}

int main() {
    testOS();
}
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|断点社区 |网站地图

GMT+8, 2025-1-18 19:00 , Processed in 0.100996 second(s), 27 queries .

Powered by XiunoBBS

Copyright © 2001-2025, 断点社区.

快速回复 返回顶部 返回列表