C++Primer第八章:IO库

啦啦啦,断更了大半年,我胡汉三又回来了。这次争取一周更一章,把这本书的笔记更完。

第八章:IO库

从第8章到第12章主要是介绍标准库的一些相关知识。第8章主要介绍的是IO库。

IO库定义了一些输入输出类型,我们能够通过这些类型具体的对象完成输入输出。

一.IO类

iostream定义了用于读写流的基本类型,fstream定义了读写命名文件的类型,sstream定义了读写内存string对象的类型。

标准库定义了一组类型和对象来操纵wchar_t类型的数据。宽字符版本的类型和函数以一个w开始。所谓宽字符可见:宽字符

不能拷贝或对IO对象赋值,所以不能将形参或返回类型设为流类型,可以设为引用类型。

IO库定义了一个与机器无关的iostate类型,它提供了表达流状态的完整功能,这个类型应作为一个位集合来使用。

每个输出流都管理一个缓冲区,所以输出不一定立即打印,可能会先存在缓冲区中。endl可以刷新缓冲。flush和ends也有类似的效果。 可以直接使用unitbuf操作符告诉流每次输出都刷新缓冲区。

标准库将cin和cout关联在一起,因此在使用cin的时候cout的缓冲区会被刷新。

tie函数可以将流之间关联。

二.文件输入输出

头文件fstream定义了三个流来读写文件,可以按照IO的方式<<>>来读写文件(因为其继承的是iostream)。

对于形参是istream&和ostream&的函数,我们可以传ifstream和ofstream。

对于每个流打开时都可以关联相应的文件模式,如果没有关联会有默认的文件模式。

三.string流

sstream定义了三个类型来支持对内存的string进行IO。

四.总结

标准库中主要定义了三个流来进行IO操作。iostream处理控制台IO;fstream处理命名文件IO;stringstream处理内存string的IO。后面两个继承自第一个。所以第一个的操作后面两个也是可以用的。例如>><<,限制也一样存在,在>><<中遇到空格和换行会进行下一条输入输出。两个最主要的点就在于这三个IO都可以方便的使用操作符进行操作且有对应的函数判断操作的状态,二是要理解流的含义,即从流中输入,输出到流中,具体与控制台或者文件或者内存string是通过流来交互的。

练习

部分答案参考:答案

8.1 8.2

#include <iostream>

std::istream& func(std::istream& temp) {
    std::string buf;
    while (!temp.eof()) {
        temp>>buf;
        std::cout << buf << std::endl;
    }
    temp.clear();
    return temp;
}

int main() {
    func(std::cin);
    return 0;
}

8.3

遇到了文件结束符,或者遇到了 IO 流错误,或者读入了无效数据。

8.4

#include <fstream>
#include <vector>
#include <iostream>

int main() {
    std::ifstream in("/home/watson/test.txt");
    std::string temp;
    std::vector<std::string> vec;
    if (!in) {
        std::cerr << "读取文件错误" << std::endl;
        return 0;
    }
    while (getline(in, temp)) {
        vec.push_back(temp);
    }

    for (auto &str : vec) {
        std::cout << str << std::endl;
    }
    return 0;
}

8.5

将8.4中程序的getline(in, temp)改为in>>temp

8.6

头文件见练习7.26

输入文件内容为:

0-201-78345-X 3 20.00 19.00
0-201-78345-X 4 20.00 19.00
0-202-78345-X 4 30.00 29.00
0-202-78345-Y 2 200.00 199.00
#include "Sales_data.h"
#include <fstream>

using namespace std;

int main(int argc, char* argv[]) {
    if (argc < 2) {
        cerr << "请输入文件路径" << endl;
    }

    ifstream in(argv[1]);
    if (!in) {
        cerr << "文件读取失败" << endl;
        return 0;
    }

    Sales_data total;               // 保存当前求和结果的变量
    if (total.read(in, total)) {             // 读入第一笔交易记录
        Sales_data trans;          // 保存下一条交易数据的变量
        while (trans.read(in, trans)) {     // 读入剩余的交易
            if (total.isbn() == trans.isbn())  // 检查 isbn
                total = total.add(total, trans);     // 更新变量 total 当前的值
            else {
                total.print(cout, total) << endl;    // 输出结果
                total = trans;                 // 处理下一本
            }
        }
        total.print(cout, total) << endl;            // 输出最后一条交易
    }
    else {                              // 没有输入任何信息
        cerr << "没有数据" << endl;    // 通知用户
        return -1;
    }
    return 0;
}

8.7

#include <iostream>
#include <fstream>
#include "Sales_data.h"
using namespace std;

int main(int argc, char *argv[]) {
    if (argc != 3) {
        cerr << "文件数量不对" << endl;
        return -1;
    }
    ifstream in(argv[1]);
    if (!in) {
        cerr << "无法打开输入文件" << endl;
        return -1;
    }

    ofstream out(argv[2]);
    if (!out) {
        cerr << "无法打开输出文件" << endl;
        return -1;
    }

    Sales_data total;               // 保存当前求和结果的变量
    if (total.read(in, total)) {             // 读入第一笔交易记录
        Sales_data trans;          // 保存下一条交易数据的变量
        while (trans.read(in, trans)) {     // 读入剩余的交易
            if (total.isbn() == trans.isbn())  // 检查 isbn
                total = total.add(total, trans);     // 更新变量 total 当前的值
            else {
                total.print(out, total) << endl;    // 输出结果
                total = trans;                 // 处理下一本
            }
        }
        total.print(out, total) << endl;            // 输出最后一条交易
    }
    else {                              // 没有输入任何信息
        cerr << "没有数据" << endl;    // 通知用户
        return -1;
    }
    return 0;
}

8.8

将ofstream out(argv[2]);改为ofstream out(argv[2], ofstream::app);

8.9

#include <iostream>
#include <sstream>

std::istream& func(std::istream& temp) {
    std::string buf;
    while (!temp.eof()) {
        temp>>buf;
        std::cout << buf << std::endl;
    }
    temp.clear();
    return temp;
}

int main() {
    std::string str = "hello world";
    std::istringstream in(str);
    func(in);
    return 0;
}

8.10

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

using namespace std;

int main() {
    ifstream in("input.txt");
    vector<string> vec;

    string line;
    while (getline(in, line)) {
        vec.push_back(line);
    }

    in.close();

    for (auto &str : vec) {
        istringstream in(str);
        string temp;
        while (in >> temp) {
            cout << temp << " ";
        }
        cout << endl;
    }
    return 0;
}

8.11

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

using namespace std;

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

int main() {
    string line, word;              // 分别保存来自输入的一行和单词
    vector<PersonInfo> people;      // 保存来自输入的所有记录
    istringstream record;

    // 逐行从输入读取数据,直至 cin 遇到文件尾(或其他错误)
    while (getline(cin, line) && line != "Q") {
        PersonInfo info;            // 创建一个保存此记录数据的对象
        record.clear();             // 重复使用字符串流时,每次都要调用 clear
        record.str(line);           // 将记录绑定到刚读入的行(将 line 拷贝到 record 中)
        record >> info.name;        // 读取名字
        while (record >> word)      // 读取电话号码
            info.phones.push_back(word);    // 保持它们
        people.push_back(info);     // 将此记录追加到 people 末尾
    }

    for (auto &p : people) {
        cout << p.name << " ";
        for (auto &s : p.phones)
            std::cout << s << " ";
        cout << endl;
    }

    return 0;
}

8.12

电话号码数量不确定

8.13 8.14

答案

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值