C++ Primer Plus 第17章:输入、输出和文件

17.1 C++ I/O 概述

17.1.1 流的概念

C++ 的 I/O 系统基于**流(Stream)**的概念:

复制代码
输入流:数据源 ──→ 程序
                键盘、文件、字符串 ──→ cin、ifstream、istringstream

输出流:程序 ──→ 数据目标
                程序 ──→ cout、ofstream、ostringstream、屏幕、文件

I/O 类层次结构:

复制代码
ios_base
    └── ios
         ├── istream ──→ ifstream, istringstream
         ├── ostream ──→ ofstream, ostringstream
         └── iostream ──→ fstream, stringstream

17.1.2 标准流对象

cpp 复制代码
// standard_streams.cpp -- 标准流对象
#include <iostream>

int main()
{
    // cin  :标准输入流(键盘)
    // cout :标准输出流(屏幕)
    // cerr :标准错误流(屏幕,不缓冲)
    // clog :标准日志流(屏幕,缓冲)

    std::cout << "这是标准输出" << std::endl;
    std::cerr << "这是错误输出(立即显示)" << std::endl;
    std::clog << "这是日志输出(缓冲)" << std::endl;

    // cout 和 cerr 的区别:
    // cerr 不缓冲,立即输出,适合错误信息
    // cout 有缓冲,适合正常输出

    return 0;
}

17.2 cout 与输出格式化

17.2.1 基本输出

cpp 复制代码
// cout_basic.cpp -- cout基本输出
#include <iostream>

int main()
{
    using namespace std;

    // 基本输出
    cout << "字符串" << endl;
    cout << 42 << endl;
    cout << 3.14 << endl;
    cout << true << endl;   // 输出1

    // 链式输出
    cout << "a=" << 1 << " b=" << 2 << " c=" << 3 << endl;

    // endl vs "\n"
    cout << "endl:刷新缓冲区" << endl;
    cout << "\\n:只换行不刷新" << "\n";

    // 输出特殊字符
    cout << "制表符:\t对齐" << endl;
    cout << "反斜杠:\\" << endl;
    cout << "引号:\"Hello\"" << endl;

    return 0;
}

17.2.2 格式化输出(iomanip)

cpp 复制代码
// format_output.cpp -- 格式化输出详解
#include <iostream>
#include <iomanip>   // 格式化操纵符

int main()
{
    using namespace std;

    // ===== 进制输出 =====
    cout << "===== 进制 =====" << endl;
    int n = 255;
    cout << "十进制:" << dec << n << endl;   // 255
    cout << "八进制:" << oct << n << endl;   // 377
    cout << "十六进制:" << hex << n << endl; // ff
    cout << "十六进制大写:" << uppercase << hex << n << endl; // FF
    cout << dec;   // 恢复十进制

    // 显示进制前缀
    cout << showbase;
    cout << "带前缀十进制:" << dec << n << endl;   // 255
    cout << "带前缀八进制:" << oct << n << endl;   // 0377
    cout << "带前缀十六进制:" << hex << n << endl; // 0xff
    cout << noshowbase << dec;

    // ===== 浮点数格式 =====
    cout << "\n===== 浮点数 =====" << endl;
    double pi = 3.14159265358979;

    cout << "默认:" << pi << endl;
    cout << fixed;
    cout << "fixed:" << pi << endl;
    cout << "fixed(2):" << setprecision(2) << pi << endl;
    cout << "fixed(6):" << setprecision(6) << pi << endl;
    cout << scientific;
    cout << "scientific:" << pi << endl;
    cout << defaultfloat;   // 恢复默认

    // ===== 宽度与对齐 =====
    cout << "\n===== 宽度对齐 =====" << endl;
    cout << setw(10) << "右对齐" << endl;   // 默认右对齐
    cout << left << setw(10) << "左对齐" << "|" << endl;
    cout << right << setw(10) << "右对齐" << "|" << endl;
    cout << internal << setw(10) << -42 << endl;   // 符号左对齐,数字右对齐

    // 填充字符
    cout << setfill('*');
    cout << setw(10) << "Hello" << endl;   // *****Hello
    cout << left << setw(10) << "Hello" << endl;   // Hello*****
    cout << setfill(' ');   // 恢复空格填充

    // ===== 综合格式化表格 =====
    cout << "\n===== 格式化表格 =====" << endl;
    cout << fixed << setprecision(2);
    cout << left
         << setw(12) << "商品"
         << right
         << setw(8)  << "数量"
         << setw(10) << "单价"
         << setw(10) << "总价" << endl;
    cout << string(40, '-') << endl;

    struct Item { string name; int qty; double price; };
    Item items[] = {
        {"苹果", 5, 3.50},
        {"香蕉", 12, 1.80},
        {"橙子", 8, 4.20}
    };

    double total = 0;
    for (const auto& item : items)
    {
        double subtotal = item.qty * item.price;
        total += subtotal;
        cout << left  << setw(12) << item.name
             << right << setw(8)  << item.qty
             << setw(10) << item.price
             << setw(10) << subtotal << endl;
    }
    cout << string(40, '-') << endl;
    cout << right << setw(30) << "合计:" << setw(10) << total << endl;

    return 0;
}

输出:

复制代码
===== 格式化表格 =====
商品            数量      单价      总价
----------------------------------------
苹果               5      3.50     17.50
香蕉              12      1.80     21.60
橙子               8      4.20     33.60
----------------------------------------
                          合计:     72.70

17.2.3 流状态标志

cpp 复制代码
// stream_flags.cpp -- 流状态标志
#include <iostream>
#include <iomanip>

int main()
{
    using namespace std;

    // 使用 flags() 获取/设置所有标志
    ios_base::fmtflags original = cout.flags();   // 保存原始标志

    // 设置多个标志
    cout.setf(ios_base::left | ios_base::showpos);
    cout << setw(10) << 42 << endl;   // +42(左对齐,显示正号)

    // 恢复原始标志
    cout.flags(original);
    cout << setw(10) << 42 << endl;   // 42(右对齐,不显示正号)

    // 常用标志
    cout.setf(ios_base::boolalpha);
    cout << true << " " << false << endl;   // true false

    cout.unsetf(ios_base::boolalpha);
    cout << true << " " << false << endl;   // 1 0

    // 精度设置
    cout.precision(4);
    cout << 3.14159 << endl;   // 3.142

    return 0;
}

17.3 cin 与输入处理

17.3.1 基本输入

cpp 复制代码
// cin_basic.cpp -- cin基本输入
#include <iostream>
#include <string>

int main()
{
    using namespace std;

    // 读取基本类型
    int    i;
    double d;
    char   c;
    string s;

    cout << "输入整数:"; cin >> i;
    cout << "输入浮点数:"; cin >> d;
    cin.ignore();   // 清除缓冲区中的换行符
    cout << "输入字符:"; cin.get(c);
    cin.ignore();
    cout << "输入字符串(含空格):"; getline(cin, s);

    cout << "\n你输入的:" << endl;
    cout << "整数:" << i << endl;
    cout << "浮点:" << d << endl;
    cout << "字符:" << c << endl;
    cout << "字符串:" << s << endl;

    return 0;
}

17.3.2 cin 的成员函数

cpp 复制代码
// cin_methods.cpp -- cin成员函数详解
#include <iostream>
#include <string>

int main()
{
    using namespace std;

    // ===== get() 系列 =====
    cout << "===== get() =====" << endl;

    // cin.get(ch):读取单个字符(含空白)
    char ch;
    cout << "输入一行文字:";
    while (cin.get(ch) && ch != '\n')
        cout << ch;
    cout << endl;

    // cin.get(buf, size):读取到换行符(不读取换行符)
    char buf[80];
    cout << "再输入一行:";
    cin.get(buf, 80);
    cout << "读取到:" << buf << endl;
    cin.ignore();   // 清除换行符

    // ===== getline() =====
    cout << "\n===== getline() =====" << endl;
    // cin.getline(buf, size):读取到换行符(读取并丢弃换行符)
    cout << "输入一行:";
    cin.getline(buf, 80);
    cout << "读取到:" << buf << endl;

    // std::getline(cin, string):读取到string
    string line;
    cout << "输入一行到string:";
    getline(cin, line);
    cout << "读取到:" << line << endl;

    // ===== peek() 和 putback() =====
    cout << "\n===== peek/putback =====" << endl;
    cout << "输入内容:";
    char first = cin.peek();   // 查看但不读取
    cout << "第一个字符是:" << first << endl;
    cin.get(ch);   // 实际读取
    cin.putback(ch);   // 放回
    cin.get(ch);   // 再次读取
    cout << "读取到:" << ch << endl;

    // ===== ignore() =====
    // cin.ignore(n, delim):忽略n个字符或直到delim
    cin.ignore(1000, '\n');   // 清除当前行剩余内容

    return 0;
}

17.3.3 流状态检测

cpp 复制代码
// stream_state.cpp -- 流状态检测
#include <iostream>
#include <string>

int main()
{
    using namespace std;

    // 流状态标志:
    // goodbit:无错误
    // eofbit :到达文件末尾
    // failbit:格式错误(如输入字母给int)
    // badbit :严重错误(流损坏)

    int sum = 0, count = 0;
    int val;

    cout << "输入整数(输入非数字结束):" << endl;
    while (cin >> val)   // 读取失败时返回false
    {
        sum += val;
        count++;
    }

    // 检查流状态
    if (cin.eof())
        cout << "到达文件末尾" << endl;
    else if (cin.fail())
        cout << "输入格式错误" << endl;
    else if (cin.bad())
        cout << "流损坏" << endl;

    // 清除错误状态(必须!否则无法继续读取)
    cin.clear();
    cin.ignore(1000, '\n');   // 清除错误输入

    if (count > 0)
        cout << "共" << count << "个数,总和=" << sum
             << " 平均=" << (double)sum/count << endl;

    // 继续读取
    string rest;
    cout << "继续输入字符串:";
    getline(cin, rest);
    cout << "读取到:" << rest << endl;

    return 0;
}

17.4 文件 I/O

17.4.1 写入文件(ofstream)

cpp 复制代码
// file_write.cpp -- 文件写入详解
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>

int main()
{
    using namespace std;

    // ===== 基本写入 =====
    ofstream outFile("output.txt");

    if (!outFile)   // 检查是否成功打开
    {
        cerr << "无法创建文件!" << endl;
        return 1;
    }

    outFile << "第一行文字" << endl;
    outFile << "整数:" << 42 << endl;
    outFile << "浮点:" << fixed << setprecision(2) << 3.14 << endl;
    outFile.close();
    cout << "写入完成:output.txt" << endl;

    // ===== 追加模式 =====
    ofstream appendFile("output.txt", ios::app);
    appendFile << "追加的内容" << endl;
    appendFile.close();
    cout << "追加完成" << endl;

    // ===== 二进制写入 =====
    ofstream binFile("data.bin", ios::binary);
    int    iVal = 12345;
    double dVal = 3.14159;
    binFile.write(reinterpret_cast<char*>(&iVal), sizeof(int));
    binFile.write(reinterpret_cast<char*>(&dVal), sizeof(double));
    binFile.close();
    cout << "二进制写入完成:data.bin" << endl;

    // ===== 写入结构体数组 =====
    struct Student {
        char   name[20];
        int    age;
        double score;
    };

    ofstream stuFile("students.bin", ios::binary);
    Student students[] = {
        {"张三", 20, 92.5},
        {"李四", 21, 88.0},
        {"王五", 19, 95.5}
    };

    for (const auto& s : students)
        stuFile.write(reinterpret_cast<const char*>(&s), sizeof(Student));
    stuFile.close();
    cout << "结构体写入完成:students.bin" << endl;

    return 0;
}

17.4.2 读取文件(ifstream)

cpp 复制代码
// file_read.cpp -- 文件读取详解
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>

int main()
{
    using namespace std;

    // ===== 逐行读取 =====
    cout << "===== 逐行读取 =====" << endl;
    ifstream inFile("output.txt");

    if (!inFile.is_open())
    {
        cerr << "无法打开文件!" << endl;
        return 1;
    }

    string line;
    int lineNum = 0;
    while (getline(inFile, line))
    {
        lineNum++;
        cout << lineNum << ": " << line << endl;
    }
    inFile.close();

    // ===== 逐词读取 =====
    cout << "\n===== 逐词读取 =====" << endl;
    ifstream wordFile("output.txt");
    string word;
    int wordCount = 0;
    while (wordFile >> word)
        wordCount++;
    cout << "单词数:" << wordCount << endl;
    wordFile.close();

    // ===== 读取格式化数据 =====
    cout << "\n===== 格式化读取 =====" << endl;
    // 假设文件格式:姓名 年龄 成绩
    ofstream tempFile("temp.txt");
    tempFile << "张三 20 92.5\n李四 21 88.0\n王五 19 95.5\n";
    tempFile.close();

    ifstream dataFile("temp.txt");
    string name;
    int    age;
    double score;
    while (dataFile >> name >> age >> score)
    {
        cout << "姓名:" << name
             << " 年龄:" << age
             << " 成绩:" << score << endl;
    }
    dataFile.close();

    // ===== 二进制读取 =====
    cout << "\n===== 二进制读取 =====" << endl;
    ifstream binFile("data.bin", ios::binary);
    int    iVal;
    double dVal;
    binFile.read(reinterpret_cast<char*>(&iVal), sizeof(int));
    binFile.read(reinterpret_cast<char*>(&dVal), sizeof(double));
    cout << "读取整数:" << iVal << endl;
    cout << "读取浮点:" << dVal << endl;
    binFile.close();

    return 0;
}

17.4.3 文件打开模式

cpp 复制代码
// file_modes.cpp -- 文件打开模式
#include <iostream>
#include <fstream>

int main()
{
    using namespace std;

    /*
    文件打开模式(可以用 | 组合):
    ios::in     读取
    ios::out    写入(默认截断)
    ios::app    追加(写入到末尾)
    ios::ate    打开后定位到末尾
    ios::trunc  截断(清空文件)
    ios::binary 二进制模式
    */

    // 只读
    ifstream f1("file.txt", ios::in);

    // 只写(截断)
    ofstream f2("file.txt", ios::out);

    // 追加
    ofstream f3("file.txt", ios::out | ios::app);

    // 读写(不截断)
    fstream f4("file.txt", ios::in | ios::out);

    // 读写(截断)
    fstream f5("file.txt", ios::in | ios::out | ios::trunc);

    // 二进制读写
    fstream f6("file.bin", ios::in | ios::out | ios::binary);

    // 演示:追加模式
    ofstream log("log.txt", ios::app);
    log << "日志条目1" << endl;
    log << "日志条目2" << endl;
    log.close();

    // 读取验证
    ifstream readLog("log.txt");
    string line;
    cout << "日志内容:" << endl;
    while (getline(readLog, line))
        cout << "  " << line << endl;

    return 0;
}

17.4.4 随机访问文件

cpp 复制代码
// random_access.cpp -- 文件随机访问
#include <iostream>
#include <fstream>
#include <string>

struct Record
{
    int    id;
    char   name[20];
    double score;
};

int main()
{
    using namespace std;

    const string filename = "records.bin";

    // ===== 写入记录 =====
    {
        ofstream out(filename, ios::binary);
        Record records[] = {
            {1, "张三", 92.5},
            {2, "李四", 88.0},
            {3, "王五", 95.5},
            {4, "赵六", 78.0},
            {5, "钱七", 85.5}
        };
        for (const auto& r : records)
            out.write(reinterpret_cast<const char*>(&r), sizeof(Record));
    }

    // ===== 随机读取第3条记录 =====
    {
        ifstream in(filename, ios::binary);

        // seekg:设置读取位置
        // tellg:获取当前读取位置
        int recordIndex = 2;   // 第3条(从0开始)
        in.seekg(recordIndex * sizeof(Record), ios::beg);

        Record r;
        in.read(reinterpret_cast<char*>(&r), sizeof(Record));
        cout << "第3条记录:ID=" << r.id
             << " 姓名=" << r.name
             << " 成绩=" << r.score << endl;
    }

    // ===== 随机修改第2条记录 =====
    {
        fstream file(filename, ios::in | ios::out | ios::binary);

        int recordIndex = 1;   // 第2条
        file.seekp(recordIndex * sizeof(Record), ios::beg);

        Record newRecord = {2, "李四(修改)", 99.0};
        file.write(reinterpret_cast<const char*>(&newRecord),
                   sizeof(Record));
    }

    // ===== 读取所有记录 =====
    {
        ifstream in(filename, ios::binary);
        Record r;
        cout << "\n所有记录:" << endl;
        while (in.read(reinterpret_cast<char*>(&r), sizeof(Record)))
        {
            cout << "ID=" << r.id
                 << " 姓名=" << r.name
                 << " 成绩=" << r.score << endl;
        }
    }

    return 0;
}

💡 seekg vs seekp

  • seekg:设置读取位置(get position)
  • seekp:设置写入位置(put position)
  • 第二个参数:ios::beg(从头)、ios::cur(当前)、ios::end(从尾)

17.5 字符串流(sstream)

cpp 复制代码
// stringstream_demo.cpp -- 字符串流
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

int main()
{
    using namespace std;

    // ===== ostringstream:写入字符串 =====
    cout << "===== ostringstream =====" << endl;
    ostringstream oss;
    oss << "姓名:" << "张三" << endl;
    oss << "年龄:" << 25 << endl;
    oss << "成绩:" << fixed << 92.5 << endl;

    string result = oss.str();   // 获取字符串
    cout << result;

    // 用于格式化字符串
    ostringstream fmt;
    fmt << "第" << 3 << "页,共" << 10 << "页";
    cout << fmt.str() << endl;

    // ===== istringstream:从字符串读取 =====
    cout << "\n===== istringstream =====" << endl;
    string data = "张三 20 92.5";
    istringstream iss(data);

    string name;
    int    age;
    double score;
    iss >> name >> age >> score;
    cout << "姓名:" << name << " 年龄:" << age
         << " 成绩:" << score << endl;

    // 解析CSV行
    cout << "\n===== 解析CSV =====" << endl;
    string csvLine = "苹果,3.50,100,水果";
    istringstream csvStream(csvLine);
    string field;
    vector<string> fields;
    while (getline(csvStream, field, ','))   // 以逗号分隔
        fields.push_back(field);

    for (size_t i = 0; i < fields.size(); i++)
        cout << "字段" << i << ":" << fields[i] << endl;

    // ===== stringstream:读写 =====
    cout << "\n===== stringstream =====" << endl;
    stringstream ss;
    ss << 42 << " " << 3.14 << " " << "Hello";

    int    i; double d; string s;
    ss >> i >> d >> s;
    cout << "读取:" << i << " " << d << " " << s << endl;

    // 类型转换(string ↔ 数值)
    auto toString = [](double val) -> string {
        ostringstream os;
        os << val;
        return os.str();
    };

    auto toDouble = [](const string& s) -> double {
        istringstream is(s);
        double val;
        is >> val;
        return val;
    };

    cout << "3.14 → string:\"" << toString(3.14) << "\"" << endl;
    cout << "\"2.71\" → double:" << toDouble("2.71") << endl;

    return 0;
}

17.6 综合示例:CSV 文件处理系统

cpp 复制代码
// csv_system.cpp -- 综合示例:CSV文件处理
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <iomanip>
#include <numeric>

struct SalesRecord
{
    std::string date;
    std::string product;
    std::string region;
    int         quantity;
    double      price;
    double      total() const { return quantity * price; }
};

class CSVProcessor
{
private:
    std::vector<SalesRecord> records;
    std::string filename;

    // 解析CSV行
    std::vector<std::string> parseLine(const std::string& line)
    {
        std::vector<std::string> fields;
        std::istringstream ss(line);
        std::string field;
        while (std::getline(ss, field, ','))
            fields.push_back(field);
        return fields;
    }

public:
    CSVProcessor(const std::string& file) : filename(file) {}

    // 写入CSV文件
    void writeCSV()
    {
        std::ofstream out(filename);
        if (!out)
        {
            std::cerr << "无法创建文件:" << filename << std::endl;
            return;
        }

        // 写入标题行
        out << "日期,产品,地区,数量,单价" << std::endl;

        // 写入数据
        std::vector<SalesRecord> data = {
            {"2024-01-15", "苹果", "北京", 100, 3.50},
            {"2024-01-15", "香蕉", "上海", 200, 1.80},
            {"2024-01-16", "苹果", "上海", 150, 3.50},
            {"2024-01-16", "橙子", "北京", 80,  4.20},
            {"2024-01-17", "香蕉", "北京", 120, 1.80},
            {"2024-01-17", "苹果", "广州", 200, 3.50},
            {"2024-01-18", "橙子", "上海", 90,  4.20},
            {"2024-01-18", "香蕉", "广州", 160, 1.80}
        };

        for (const auto& r : data)
            out << r.date << "," << r.product << ","
                << r.region << "," << r.quantity << ","
                << r.price << std::endl;

        std::cout << "CSV文件已创建:" << filename << std::endl;
    }

    // 读取CSV文件
    bool readCSV()
    {
        std::ifstream in(filename);
        if (!in)
        {
            std::cerr << "无法打开文件:" << filename << std::endl;
            return false;
        }

        records.clear();
        std::string line;
        bool firstLine = true;

        while (std::getline(in, line))
        {
            if (firstLine) { firstLine = false; continue; }   // 跳过标题
            if (line.empty()) continue;

            auto fields = parseLine(line);
            if (fields.size() >= 5)
            {
                SalesRecord r;
                r.date     = fields[0];
                r.product  = fields[1];
                r.region   = fields[2];
                r.quantity = std::stoi(fields[3]);
                r.price    = std::stod(fields[4]);
                records.push_back(r);
            }
        }

        std::cout << "读取 " << records.size() << " 条记录" << std::endl;
        return true;
    }

    // 打印所有记录
    void printAll() const
    {
        using namespace std;
        cout << "\n" << string(60, '=') << endl;
        cout << left
             << setw(12) << "日期"
             << setw(8)  << "产品"
             << setw(8)  << "地区"
             << right
             << setw(6)  << "数量"
             << setw(8)  << "单价"
             << setw(10) << "小计" << endl;
        cout << string(60, '-') << endl;

        for (const auto& r : records)
        {
            cout << left
                 << setw(12) << r.date
                 << setw(8)  << r.product
                 << setw(8)  << r.region
                 << right
                 << setw(6)  << r.quantity
                 << setw(8)  << fixed << setprecision(2) << r.price
                 << setw(10) << r.total() << endl;
        }
        cout << string(60, '=') << endl;
    }

    // 按产品统计
    void analyzeByProduct() const
    {
        using namespace std;
        map<string, pair<int, double>> stats;   // 产品→{总数量, 总金额}

        for (const auto& r : records)
        {
            stats[r.product].first  += r.quantity;
            stats[r.product].second += r.total();
        }

        cout << "\n===== 按产品统计 =====" << endl;
        cout << left << setw(10) << "产品"
             << right << setw(8) << "总数量"
             << setw(12) << "总金额" << endl;
        cout << string(30, '-') << endl;

        for (const auto& [product, data] : stats)
            cout << left  << setw(10) << product
                 << right << setw(8)  << data.first
                 << setw(12) << fixed << setprecision(2) << data.second
                 << endl;
    }

    // 按地区统计
    void analyzeByRegion() const
    {
        using namespace std;
        map<string, double> regionSales;

        for (const auto& r : records)
            regionSales[r.region] += r.total();

        // 按销售额排序
        vector<pair<string, double>> sorted(regionSales.begin(),
                                            regionSales.end());
        sort(sorted.begin(), sorted.end(),
             [](const auto& a, const auto& b) { return a.second > b.second; });

        cout << "\n===== 按地区统计(降序)=====" << endl;
        for (const auto& [region, sales] : sorted)
            cout << region << ":" << fixed << setprecision(2)
                 << sales << " 元" << endl;
    }

    // 总销售额
    double totalSales() const
    {
        return std::accumulate(records.begin(), records.end(), 0.0,
            [](double sum, const SalesRecord& r) { return sum + r.total(); });
    }
};

int main()
{
    CSVProcessor processor("sales.csv");

    // 写入数据
    processor.writeCSV();

    // 读取数据
    processor.readCSV();

    // 打印所有记录
    processor.printAll();

    // 分析
    processor.analyzeByProduct();
    processor.analyzeByRegion();

    std::cout << "\n总销售额:" << std::fixed << std::setprecision(2)
              << processor.totalSales() << " 元" << std::endl;

    return 0;
}

📝 第17章知识点总结

知识点 核心要点
流的概念 数据在程序与外部之间的流动,输入流/输出流
标准流 cin(输入)、cout(输出)、cerr(错误,不缓冲)、clog(日志,缓冲)
格式化输出 setw(宽度)、setprecision(精度)、fixed/scientificleft/rightsetfill
进制输出 dec/oct/hexshowbase显示前缀、uppercase
cin 读取 >>跳过空白、get()读取含空白、getline()读取整行
流状态 good()/eof()/fail()/bad()clear()清除错误状态
ofstream 写入文件,ios::app追加,ios::binary二进制
ifstream 读取文件,getline逐行,>>逐词,read二进制
文件模式 in/out/app/ate/trunc/binary,可用`
随机访问 seekg/seekp定位,tellg/tellp获取位置,ios::beg/cur/end
ostringstream 写入字符串,str()获取结果,用于格式化字符串
istringstream 从字符串读取,用于解析CSV等格式化文本
fstream 同时支持读写,需指定打开模式
二进制I/O write()/read()reinterpret_cast<char*>转换指针
相关推荐
枫叶丹41 小时前
【HarmonyOS 6.0】Live View Kit 实况窗开发详解:进度胶囊支持副文本功能探究
开发语言·华为·harmonyos
SilentSamsara1 小时前
FastAPI 实战:从路由定义到依赖注入的完整 REST API
开发语言·python·青少年编程·fastapi
j_xxx404_1 小时前
Linux 线程同步硬核解析:从条件变量、阻塞队列到信号量环形队列
linux·运维·服务器·c++·人工智能·ai·中间件
Zhang~Ling1 小时前
二叉搜索树(BST)详解:插入、删除、查找与 Key/Value 实战场景
数据结构·c++·算法
AI人工智能+电脑小能手1 小时前
【大白话说Java面试题 第86题】【Mysql篇】第16题:MySQL 中锁的种类与行锁实现原理?
java·开发语言·数据库·mysql·面试
不爱编程的小陈1 小时前
Go内存模型与GC机制:高性能编程的核心
开发语言·后端·golang
右耳朵猫AI1 小时前
PHP技术周刊 2026年第20周
开发语言·php
方也_arkling2 小时前
【Java-Day12】接口
java·开发语言
小小de风呀2 小时前
de风——【从零开始学 C++】(十)vector的模拟实现
开发语言·c++