# ===== CodeLab: cpp-exceptions =====
# 以下代码片段按文章出现顺序拼接, 共 7 段

# ----- 片段 1 (cpp) -----
#include <iostream>

// 错误码方案:每层都要检查、都要传递
int read_config(const char* path) {
    FILE* f = fopen(path, "r");
    if (!f) return -1;          // 文件不存在
    fclose(f);
    return 0;
}

int load_app() {
    int ret = read_config("app.conf");
    if (ret != 0) return ret;   // 层层上抛,忘了检查就悄悄失败
    return 0;
}

int main() {
    if (load_app() != 0) {
        std::cout << "加载失败\n";
        return 1;
    }
    std::cout << "启动成功\n";
    return 0;
}

# ----- 片段 2 (cpp) -----
#include <iostream>
#include <stdexcept>

double divide(double a, double b) {
    if (b == 0) {
        throw std::runtime_error("除数不能为 0");
    }
    return a / b;
}

int main() {
    try {
        std::cout << divide(10, 2) << "\n";   // 5
        std::cout << divide(10, 0) << "\n";   // 这里抛出
        std::cout << "这行不会执行\n";
    } catch (const std::runtime_error& e) {
        std::cout << "捕获: " << e.what() << "\n";
    }
    std::cout << "程序继续运行\n";
    return 0;
}

# ----- 片段 3 (cpp) -----
#include <iostream>
#include <stdexcept>
#include <string>
#include <utility>

struct Tracker {
    std::string name;
    explicit Tracker(std::string n) : name(std::move(n)) {
        std::cout << "构造 " << name << "\n";
    }
    ~Tracker() { std::cout << "析构 " << name << "\n"; }
};

void inner() {
    Tracker t("inner 局部对象");
    throw std::runtime_error("inner 出错");
}

void outer() {
    Tracker t("outer 局部对象");
    inner();   // 异常穿过 outer
}

int main() {
    try {
        outer();
    } catch (const std::exception& e) {
        std::cout << "捕获: " << e.what() << "\n";
    }
    return 0;
}

# ----- 片段 4 (cpp) -----
#include <iostream>
#include <stdexcept>

int main() {
    try {
        throw std::out_of_range("下标越界");
    } catch (const std::out_of_range& e) {
        std::cout << "具体处理: " << e.what() << "\n";
    } catch (const std::exception& e) {
        std::cout << "通用处理: " << e.what() << "\n";
    } catch (...) {
        std::cout << "未知异常\n";
    }
    return 0;
}

# ----- 片段 5 (cpp) -----
#include <iostream>
#include <stdexcept>
#include <string>

class ConfigError : public std::runtime_error {
public:
    explicit ConfigError(const std::string& msg)
        : std::runtime_error(msg) {}
};

void load_config(const std::string& path) {
    if (path.empty()) {
        throw ConfigError("配置文件路径为空");
    }
}

int main() {
    try {
        load_config("");
    } catch (const ConfigError& e) {
        std::cout << "配置错误: " << e.what() << "\n";
    }
    return 0;
}

# ----- 片段 6 (cpp) -----
#include <cstdlib>
#include <iostream>
#include <memory>
#include <stdexcept>

void risky() {
    // 不要这样写!异常时 delete 不会执行
    int* p = new int(42);
    if (std::rand() % 2 == 0) throw std::runtime_error("随机失败");
    delete p;
}

void safe() {
    // RAII:unique_ptr 析构时自动释放,异常也拦不住它
    std::unique_ptr<int> p = std::make_unique<int>(42);
    if (std::rand() % 2 == 0) throw std::runtime_error("随机失败");
    std::cout << *p << "\n";
}

int main() {
    try {
        risky();
    } catch (const std::exception&) {
        std::cout << "risky 可能泄漏了内存\n";
    }
    try {
        safe();
    } catch (const std::exception&) {
        std::cout << "safe 的 p 已被自动释放\n";
    }
    return 0;
}

# ----- 片段 7 (cpp) -----
#include <fstream>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>

std::string read_file(const std::string& path) {
    std::ifstream in(path);
    if (!in) {
        throw std::runtime_error("无法打开文件: " + path);
    }
    std::ostringstream buf;
    buf << in.rdbuf();   // 把整个文件内容倒进字符串流
    return buf.str();
}

int main() {
    try {
        std::string content = read_file("no_such_file.txt");
        std::cout << "内容长度: " << content.size() << "\n";
    } catch (const std::exception& e) {
        std::cout << "出错: " << e.what() << "\n";
    }
    return 0;
}
