8C++ Primer(第5版)

IO库

输入输出操作

iostream文件流字符串流

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第8章:IO库(IO Library)

一、导读

1.1 本章学习目标

第8章介绍C++的IO库。本章核心目标:

  • 掌握标准IO:cin、cout、cerr的使用
  • 学会文件IO:ifstream、ofstream、fstream
  • 理解字符串流:istringstream、ostringstream
  • 掌握IO状态管理:good()、fail()、eof()、bad()
  • 学会格式化输出:setw、setprecision等

1.2 为什么本章如此重要

IO是程序与外部世界交互的通道。C++的IO库是面向对象的,支持类型安全的操作,比C的stdio更安全、更灵活。

1.3 核心问题引导

cin/cout和printf/scanf有什么本质区别?

文件打开失败时如何检测?

字符串流有什么实际用途?

IO状态标志在什么时候会改变?


二、核心概念详解

8.1 标准IO

cpp
#include <iostream>
#include <string>

int main() {
    // 标准输出
    std::cout << "Hello, World!" << std::endl;
    std::cout << "The answer is " << 42 << std::endl;
    
    // 标准输入
    int age;
    std::string name;
    std::cout << "Enter name and age: ";
    std::cin >> name >> age;
    std::cout << "Hello, " << name << "! Age: " << age << std::endl;
    
    // 读取整行
    std::string line;
    std::cout << "Enter a sentence: ";
    std::getline(std::cin, line);
    std::cout << "You said: " << line << std::endl;
    
    // 标准错误
    std::cerr << "Error: something went wrong!" << std::endl;
    std::clog << "Log: this is a log message" << std::endl;
    
    return 0;
}

8.2 文件IO

cpp
#include <iostream>
#include <fstream>
#include <string>

int main() {
    // 写入文件
    std::ofstream outfile("test.txt");
    if (!outfile) {
        std::cerr << "Error opening file for writing" << std::endl;
        return 1;
    }
    outfile << "Hello, File!" << std::endl;
    outfile << "Line 2: " << 42 << std::endl;
    outfile.close();
    
    // 读取文件
    std::ifstream infile("test.txt");
    if (!infile) {
        std::cerr << "Error opening file for reading" << std::endl;
        return 1;
    }
    std::string line;
    while (std::getline(infile, line)) {
        std::cout << line << std::endl;
    }
    infile.close();
    
    // 追加模式
    std::ofstream appfile("test.txt", std::ios::app);
    appfile << "Appended line" << std::endl;
    appfile.close();
    
    // 读写模式
    std::fstream iofile("test.txt", std::ios::in | std::ios::out);
    if (iofile) {
        std::string first_line;
        std::getline(iofile, first_line);
        std::cout << "First line: " << first_line << std::endl;
        iofile.close();
    }
    
    return 0;
}

8.3 字符串流

cpp
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>

int main() {
    // ostringstream:构建字符串
    std::ostringstream oss;
    oss << "Name: Alice, Age: " << 20 
        << ", Score: " << std::fixed << std::setprecision(2) << 95.5;
    std::string result = oss.str();
    std::cout << result << std::endl;
    
    // istringstream:解析字符串
    std::istringstream iss("123 45.67 hello");
    int num;
    double d;
    std::string str;
    iss >> num >> d >> str;
    std::cout << num << ", " << d << ", " << str << std::endl;
    
    // 格式化输出
    double pi = 3.14159265358979;
    std::cout << std::setw(15) << std::setprecision(4) << pi << std::endl;
    std::cout << std::setw(15) << std::left << pi << std::endl;
    std::cout << std::setw(15) << std::right << pi << std::endl;
    
    // 进制转换
    int value = 255;
    std::cout << "Decimal: " << std::dec << value << std::endl;
    std::cout << "Hex: " << std::hex << value << std::endl;
    std::cout << "Octal: " << std::oct << value << std::endl;
    
    return 0;
}

8.4 IO状态管理

cpp
#include <iostream>
#include <fstream>

int main() {
    std::ifstream file("test.txt");
    
    // 检查IO状态
    if (file.good()) {
        std::cout << "Stream is in good state" << std::endl;
    }
    
    // 逐词读取
    std::string word;
    while (file >> word) {
        std::cout << word << " ";
    }
    
    // 检查为什么循环结束
    if (file.eof()) {
        std::cout << "\nReached end of file" << std::endl;
    }
    if (file.fail()) {
        std::cout << "A format error occurred" << std::endl;
    }
    if (file.bad()) {
        std::cout << "A serious I/O error occurred" << std::endl;
    }
    
    // 清除错误状态
    file.clear();
    
    file.close();
    return 0;
}

三、实战案例

3.1 文件复制程序

cpp
#include <iostream>
#include <fstream>
#include <string>

bool copyFile(const std::string &src, const std::string &dst) {
    std::ifstream infile(src, std::ios::binary);
    if (!infile) {
        std::cerr << "Cannot open source file: " << src << std::endl;
        return false;
    }
    
    std::ofstream outfile(dst, std::ios::binary);
    if (!outfile) {
        std::cerr << "Cannot open destination file: " << dst << std::endl;
        return false;
    }
    
    char buffer[4096];
    while (infile.read(buffer, sizeof(buffer))) {
        outfile.write(buffer, infile.gcount());
    }
    // 写入剩余数据
    outfile.write(buffer, infile.gcount());
    
    infile.close();
    outfile.close();
    return true;
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        std::cerr << "Usage: " << argv[0] << " source destination" << std::endl;
        return 1;
    }
    
    if (copyFile(argv[1], argv[2])) {
        std::cout << "File copied successfully" << std::endl;
    }
    
    return 0;
}

3.2 简单的CSV解析器

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

struct Record {
    std::string name;
    int age;
    std::string city;
};

std::vector<Record> readCSV(const std::string &filename) {
    std::vector<Record> records;
    std::ifstream file(filename);
    
    std::string line;
    std::getline(file, line);  // 跳过标题行
    
    while (std::getline(file, line)) {
        std::istringstream iss(line);
        Record r;
        std::string token;
        
        std::getline(iss, token, ',');
        r.name = token;
        
        std::getline(iss, token, ',');
        r.age = std::stoi(token);
        
        std::getline(iss, token, ',');
        r.city = token;
        
        records.push_back(r);
    }
    
    return records;
}

int main() {
    // 创建测试CSV
    std::ofstream csv("data.csv");
    csv << "name,age,city" << std::endl;
    csv << "Alice,20,Beijing" << std::endl;
    csv << "Bob,25,Shanghai" << std::endl;
    csv << "Charlie,30,Guangzhou" << std::endl;
    csv.close();
    
    auto records = readCSV("data.csv");
    for (const auto &r : records) {
        std::cout << r.name << ", " << r.age << ", " << r.city << std::endl;
    }
    
    return 0;
}

四、本章小结

第8章介绍了C++的IO库:标准IO(cin/cout/cerr)、文件IO(ifstream/ofstream/fstream)、字符串流(istringstream/ostringstream)、IO状态管理、格式化输出。


五、思考与练习

思考题

cout和cerr有什么区别?什么时候用cerr?

文件打开失败时如何检测和处理?

字符串流在什么场景下特别有用?

二进制模式和文本模式有什么区别?

编程练习

实现一个简单的文本搜索工具,在文件中查找关键词。

编写程序读取JSON文件并解析。

实现一个日志系统,支持不同级别的日志输出。


8/12IO库
0%