From 606fbc6ff1010e6fbf8643f28ee87b1ccc326025 Mon Sep 17 00:00:00 2001 From: flykhan Date: Wed, 2 Aug 2023 19:23:29 +0800 Subject: [PATCH] day8: coding --- day8/d1.cpp | 21 ++++++++++ day8/d10.cpp | 81 +++++++++++++++++++++++++++++++++++++++ day8/d11.cpp | 37 ++++++++++++++++++ day8/d12.cpp | 83 ++++++++++++++++++++++++++++++++++++++++ day8/d13.cpp | 91 ++++++++++++++++++++++++++++++++++++++++++++ day8/d2.cpp | 30 +++++++++++++++ day8/d3.cpp | 75 ++++++++++++++++++++++++++++++++++++ day8/d4.cpp | 71 ++++++++++++++++++++++++++++++++++ day8/d5.cpp | 29 ++++++++++++++ day8/d6.cpp | 45 ++++++++++++++++++++++ day8/d7.cpp | 53 ++++++++++++++++++++++++++ day8/d8.cpp | 51 +++++++++++++++++++++++++ day8/d9.cpp | 53 ++++++++++++++++++++++++++ day8/stl_code/d1.cpp | 27 +++++++++++++ day8/stl_code/d2.cpp | 46 ++++++++++++++++++++++ day8/stl_code/d3.cpp | 48 +++++++++++++++++++++++ day8/stl_code/d4.cpp | 1 + 17 files changed, 842 insertions(+) create mode 100644 day8/d1.cpp create mode 100644 day8/d10.cpp create mode 100644 day8/d11.cpp create mode 100644 day8/d12.cpp create mode 100644 day8/d13.cpp create mode 100644 day8/d2.cpp create mode 100644 day8/d3.cpp create mode 100644 day8/d4.cpp create mode 100644 day8/d5.cpp create mode 100644 day8/d6.cpp create mode 100644 day8/d7.cpp create mode 100644 day8/d8.cpp create mode 100644 day8/d9.cpp create mode 100644 day8/stl_code/d1.cpp create mode 100644 day8/stl_code/d2.cpp create mode 100644 day8/stl_code/d3.cpp diff --git a/day8/d1.cpp b/day8/d1.cpp new file mode 100644 index 0000000..2250ff5 --- /dev/null +++ b/day8/d1.cpp @@ -0,0 +1,21 @@ +// 抛出异常 +#include + +using namespace std; + +int div(int a, int b) +{ + if (b == 0) + { + throw "除数不能为0"; + } + return a / b; +} + +int main() +{ + cout << "-----aaaaa-----" << endl; + int ret = div(20, 0); + cout << ret << endl; + return 0; +} diff --git a/day8/d10.cpp b/day8/d10.cpp new file mode 100644 index 0000000..848f089 --- /dev/null +++ b/day8/d10.cpp @@ -0,0 +1,81 @@ +// 异常的多态 +#include +#include +#include + +using namespace std; + +class Exception +{ +private: + string msg; + +public: + Exception() + { + this->msg = ""; + cout << this << " : Exception()" << endl; + } + Exception(const string &msg) + { + this->msg = msg; + cout << this << " : Exception(const string &)" << endl; + } + Exception(const Exception &other) + { + this->msg = other.msg; + cout << this << " : Exception(const Exception &)" << endl; + } + ~Exception() { cout << this << " : ~Exception()" << endl; } + +public: + string &getMsg() // const 表示该成员函数不会修改成员变量 + { + return this->msg; + } +}; + +class ZeroDivisionException : public Exception +{ +public: + ZeroDivisionException() {} + ZeroDivisionException(const string &msg) : Exception(msg) {} +}; + +class OutOfRangeException : public Exception +{ +public: + OutOfRangeException() {} + OutOfRangeException(const string &msg) : Exception(msg) {} +}; + +int main(int argc, char const *argv[]) +{ + int n = atoi(argv[1]); + try + { + if (n == 0) + // 抛出子类的异常对象 + throw ZeroDivisionException("除数为不能 0"); + else if (n >= 20) + throw OutOfRangeException("范围越界 20"); + else if (n == 10) + throw Exception("n 不能为 10"); + else + cout << "n = " << n << endl; + } + catch (ZeroDivisionException &error) // 接子类引用 + { + cout << "精准捕获到子类异常: " << error.getMsg() << endl; + } + catch (Exception &e) // 接父类引用(要写到子类异常的后面) + { + cout << "捕获异常: " << e.getMsg() << endl; + } + catch (...) // 捕获所有异常 + { + cout << "捕获所有异常" << endl; + } + + return 0; +} \ No newline at end of file diff --git a/day8/d11.cpp b/day8/d11.cpp new file mode 100644 index 0000000..2a702c2 --- /dev/null +++ b/day8/d11.cpp @@ -0,0 +1,37 @@ +// exception 的使用 +// invalid_argument: 用于处理无效参数异常 +#include +#include +#include +#include + +using namespace std; + +int maxVal(int a, int b) +{ + if (a == b) + { + char msg[100]; + sprintf(msg, "两个参数不能相等,a = %d, b = %d", a, b); + throw invalid_argument(msg); + } + return a > b ? a : b; +} + +int main(int argc, char const *argv[]) +{ + int a = atoi(argv[1]); + int b = atoi(argv[2]); + + try + { + int ret = maxVal(a, b); + cout << "maxValue is " << ret << endl; + } + catch (exception &error) + { + cout << "error: " << error.what() << endl; // what() 返回异常信息,异常信息是一个字符串 + } + + return 0; +} \ No newline at end of file diff --git a/day8/d12.cpp b/day8/d12.cpp new file mode 100644 index 0000000..4e83f25 --- /dev/null +++ b/day8/d12.cpp @@ -0,0 +1,83 @@ +// 异常与模版 +// 异常处理循环问题的示例 +#include +#include + +using namespace std; + +template +class Stack +{ +private: + T *mData; // 数据 + int mCapacity; // 容量 + int mIndex; // 索引 + +public: + // -1 表示栈为空 + Stack(int capacity) : mCapacity(capacity), mIndex(-1) + { + this->mData = new T[this->mCapacity]; + } + ~Stack() + { + delete[] this->mData; // 释放内存 + mData = nullptr; // 防止野指针 + } + +public: + T pop() throw(out_of_range) + { + if (mIndex < 0) + throw out_of_range("当前栈未空,请先压栈"); + return this->mData[this->mIndex--]; + } + Stack &push(const T &item) throw(out_of_range) + { + if (mIndex >= mCapacity - 1) // >= 表示栈满 , mCapacity - 1 表示栈顶 + throw out_of_range("当前栈已满,请先出栈"); + this->mData[++this->mIndex] = item; + return *this; // 返回当前对象,支持链式编程 + } + T &at(int index) throw(out_of_range) + { + // mIndex == -1 表示栈为空,index < 0 表示索引小于 0,index > mIndex 表示索引大于栈顶 + if (mIndex == -1 || index < 0 || index > mIndex) + throw out_of_range("当前栈为空或位置无效"); + return this->mData[index]; + } + int size() const + { + return this->mIndex + 1; + } +}; + +int main() +{ + Stack s1(5); + s1.push(10).push(20).push(30); + for (int i = 0; i < s1.size(); i++) + cout << s1.at(i) << endl; + + cout << "*** 弹出数据 ***" << endl; + // 清空数据 + while (1) + + { + try + { + cout << s1.pop() << endl; + } + catch (exception &e) + { + cout << "error: " << e.what() << endl; + break; // 异常处理: 跳出循环 + } + } + + cout << "*** 弹栈完成,重新打印 ***" << endl; + for (int i = 0; i < s1.size(); i++) + cout << s1.at(i) << endl; + + return 0; +} diff --git a/day8/d13.cpp b/day8/d13.cpp new file mode 100644 index 0000000..29eab00 --- /dev/null +++ b/day8/d13.cpp @@ -0,0 +1,91 @@ +// 自定义标准异常类 +#include +#include + +using namespace std; + +class OutOfRangeError : public exception +{ +public: + virtual const char *what() const throw() + { + return "访问索引越界"; + } +}; + +template +class Stack +{ +private: + T *mData; // 数据 + int mCapacity; // 容量 + int mIndex; // 索引 + +public: + // -1 表示栈为空 + Stack(int capacity) : mCapacity(capacity), mIndex(-1) + { + this->mData = new T[this->mCapacity]; + } + ~Stack() + { + delete[] this->mData; // 释放内存 + mData = nullptr; // 防止野指针 + } + +public: + T pop() throw(OutOfRangeError) + { + if (mIndex < 0) + throw OutOfRangeError(); + return this->mData[this->mIndex--]; + } + Stack &push(const T &item) throw(OutOfRangeError) + { + if (mIndex >= mCapacity - 1) // >= 表示栈满 , mCapacity - 1 表示栈顶 + throw OutOfRangeError(); + this->mData[++this->mIndex] = item; + return *this; // 返回当前对象,支持链式编程 + } + T &at(int index) throw(OutOfRangeError) + { + // mIndex == -1 表示栈为空,index < 0 表示索引小于 0,index > mIndex 表示索引大于栈顶 + if (mIndex == -1 || index < 0 || index > mIndex) + throw OutOfRangeError(); + return this->mData[index]; + } + int size() const + { + return this->mIndex + 1; + } +}; + +int main() +{ + Stack s1(5); + s1.push(10).push(20).push(30); + for (int i = 0; i < s1.size(); i++) + cout << s1.at(i) << endl; + + cout << "*** 弹出数据 ***" << endl; + // 清空数据 + while (1) + + { + try + { + cout << s1.pop() << endl; + } + catch (exception &e) + { + cout << "error: " << e.what() << endl; + break; // 异常处理: 跳出循环 + } + } + + cout << "*** 弹栈完成,重新打印 ***" << endl; + for (int i = 0; i < s1.size(); i++) + cout << s1.at(i) << endl; + + return 0; +} diff --git a/day8/d2.cpp b/day8/d2.cpp new file mode 100644 index 0000000..58e6a27 --- /dev/null +++ b/day8/d2.cpp @@ -0,0 +1,30 @@ +// 处理异常的语法 +// 捕获基本数据类型的异常 +#include + +using namespace std; + +int div(int a, int b) +{ + if (b == 0) + { + throw "除数不能为0"; // 抛出异常 + } + return a / b; +} + +int main() +{ + cout << "-----aaaaa-----" << endl; + int ret = 0; + try // 捕获异常 + { + ret = div(20, 0); + } + catch (const char *err) // 捕获异常 + { + cout << "异常: " << err << endl; // 处理异常 + } + cout << "ret = " << ret << endl; + return 0; +} \ No newline at end of file diff --git a/day8/d3.cpp b/day8/d3.cpp new file mode 100644 index 0000000..ec3bd12 --- /dev/null +++ b/day8/d3.cpp @@ -0,0 +1,75 @@ +// throw 的限制 +// 在使用 throw 抛出异常信息时,受到函数声明处的 throw() 声明的 +// 可抛出异常类型的限制。 + +// 如: 函数内可以抛出任何异常 +#include + +using namespace std; + +class A +{ +public: + int n; + +public: + A(int n = 0) : n(n) {} +}; + +// throw() 声明表示不抛出任何异常 +// throw(int, char, double, A) 表示可以抛出 int, char, double, A 类型的异常 +void show(int x) throw(int, char, double, A) +{ + switch (x) + { + case 1: + throw 0; + break; + case 2: + throw 'a'; + break; + case 3: + throw "abc"; + break; + case 4: + throw 1.25; + break; + case 5: + throw A(100); // 抛出自定义类的对象 + break; + // default 可以不写,因为前面已经覆盖了所有情况 + } + cout << "x = " << x << endl; +} + +int main() +{ + cout << "输入一个整数: "; + int x; + cin >> x; + try + { + show(x); + } + catch (const int &error) + { + cout << "捕获异常: " << error << endl; + } + catch (const char &error) + { + cout << "捕获异常: " << error << endl; + } + catch (const char *error) + { + cout << "捕获异常: " << error << endl; + } + catch (const double &error) + { + cout << "捕获异常: " << error << endl; + } + catch (const A &error) + { + cout << "捕获异常: " << error.n << endl; + } + return 0; +} diff --git a/day8/d4.cpp b/day8/d4.cpp new file mode 100644 index 0000000..9217dca --- /dev/null +++ b/day8/d4.cpp @@ -0,0 +1,71 @@ +// 限制函数抛出异常 +// throw() 声明表示不抛出任何异常 +#include + +using namespace std; + +class A +{ +public: + int n; + +public: + A(int n = 0) : n(n) {} +}; + +// throw() 声明表示不抛出任何异常 +void show(int x) throw() +{ + switch (x) + { + case 1: + throw 0; + break; + case 2: + throw 'a'; + break; + case 3: + throw "abc"; + break; + case 4: + throw 1.25; + break; + case 5: + throw A(100); // 抛出自定义类的对象 + break; + // default 可以不写,因为前面已经覆盖了所有情况 + } + cout << "x = " << x << endl; +} + +int main() +{ + cout << "输入一个整数: "; + int x; + cin >> x; + try + { + show(x); + } + catch (const int &error) + { + cout << "捕获异常: " << error << endl; + } + catch (const char &error) + { + cout << "捕获异常: " << error << endl; + } + catch (const char *error) + { + cout << "捕获异常: " << error << endl; + } + catch (const double &error) + { + cout << "捕获异常: " << error << endl; + } + catch (const A &error) + { + cout << "捕获异常: " << error.n << endl; + } + return 0; +} diff --git a/day8/d5.cpp b/day8/d5.cpp new file mode 100644 index 0000000..29c2635 --- /dev/null +++ b/day8/d5.cpp @@ -0,0 +1,29 @@ +// 栈解旋(unwinding):当抛出异常时,会调用所有对象的析构函数 +#include +#include +#include + +using namespace std; + +class A +{ +public: + A() { cout << "A()" << endl; } + ~A() { cout << "~A()" << endl; } +}; + +int main() +{ + try + { + A a1; + // 栈解旋(unwinding):当抛出异常时,会调用所有对象的析构函数 + throw 0; // 抛出异常时,则会调用 a1 的析构函数 + } + catch (...) // ... 表示其他异常,可以不写,写的话必须放在最后 + { + cout << "异常被处理" << endl; + } + + return 0; +} diff --git a/day8/d6.cpp b/day8/d6.cpp new file mode 100644 index 0000000..26b516d --- /dev/null +++ b/day8/d6.cpp @@ -0,0 +1,45 @@ +// 异常接口声明 + +// 如: 结构体作为异常对象 +#include +#include +using namespace std; + +struct ERROR_S +{ + string title; // 错误信息 + int errnum; // 错误码 +} error_1; // ERROR_S error_1; // error_1 是一个全局变量 + +void test1(int n) throw(ERROR_S, int) +{ + if (n == 0) + { + error_1.title = "n 参数不能为 0"; + error_1.errnum = 1; + throw error_1; + } + else if (n == 1) + { + throw 2; + } + cout << "n = " << n << endl; +} + +int main() +{ + try + { + test1(1); + } + catch (const ERROR_S &error) + { + cout << "捕获异常: " << error.title << endl; + cout << "错误码: " << error.errnum << endl; + } + catch (...) + { // ... 表示其他异常 + cout << "捕获其他异常" << endl; + } + return 0; +} diff --git a/day8/d7.cpp b/day8/d7.cpp new file mode 100644 index 0000000..b95d0ce --- /dev/null +++ b/day8/d7.cpp @@ -0,0 +1,53 @@ +// 异常变量生命周期 +// 如 1: 抛出对象,接收对象,会使用拷贝构造函数 +// 异常变量生命周期 +// 如 1: 抛出对象,接收引用,不会使用拷贝构造函数,会直接使用构造函数 +#include +#include +#include + +using namespace std; + +class Exception +{ +private: + string msg; + +public: + Exception() + { + this->msg = ""; + cout << this << "Exception()" << endl; + } + Exception(const string &msg) + { + this->msg = msg; + cout << this << "Exception(const string &)" << endl; + } + Exception(const Exception &other) + { + this->msg = other.msg; + cout << this << "Exception(const Exception &)" << endl; + } + ~Exception() { cout << this << "~Exception()" << endl; } + +public: + string &getMsg() // const 表示该成员函数不会修改成员变量 + { + return this->msg; + } +}; + +int main() +{ + try + { + throw Exception("异常"); + } + catch (Exception e) + { + cout << "捕获异常: " << e.getMsg() << endl; + } + + return 0; +} \ No newline at end of file diff --git a/day8/d8.cpp b/day8/d8.cpp new file mode 100644 index 0000000..6c4227c --- /dev/null +++ b/day8/d8.cpp @@ -0,0 +1,51 @@ +// 异常变量生命周期 +// 如 1: 抛出对象,接收引用,不会使用拷贝构造函数,会直接使用构造函数 +#include +#include +#include + +using namespace std; + +class Exception +{ +private: + string msg; + +public: + Exception() + { + this->msg = ""; + cout << this << "Exception()" << endl; + } + Exception(const string &msg) + { + this->msg = msg; + cout << this << "Exception(const string &)" << endl; + } + Exception(const Exception &other) + { + this->msg = other.msg; + cout << this << "Exception(const Exception &)" << endl; + } + ~Exception() { cout << this << "~Exception()" << endl; } + +public: + string &getMsg() // const 表示该成员函数不会修改成员变量 + { + return this->msg; + } +}; + +int main() +{ + try + { + throw Exception("异常"); + } + catch (Exception &e) + { + cout << "捕获异常: " << e.getMsg() << endl; + } + + return 0; +} \ No newline at end of file diff --git a/day8/d9.cpp b/day8/d9.cpp new file mode 100644 index 0000000..a60de79 --- /dev/null +++ b/day8/d9.cpp @@ -0,0 +1,53 @@ +// 异常变量生命周期 +// 如 1: 抛出对象(堆区),捕获对象(堆区),会使用拷贝构造函数,需要手动释放内存 +#include +#include +#include + +using namespace std; + +class Exception +{ +private: + string msg; + +public: + Exception() + { + this->msg = ""; + cout << this << "Exception()" << endl; + } + Exception(const string &msg) + { + this->msg = msg; + cout << this << "Exception(const string &)" << endl; + } + Exception(const Exception &other) + { + this->msg = other.msg; + cout << this << "Exception(const Exception &)" << endl; + } + ~Exception() { cout << this << "~Exception()" << endl; } + +public: + string &getMsg() // const 表示该成员函数不会修改成员变量 + { + return this->msg; + } +}; + +int main() +{ + try + { + // 要使用 new 创建对象,否则会在栈区创建对象,导致异常抛出时,会调用析构函数 + throw new Exception("异常"); // 在堆区创建对象 + } + catch (Exception *e) + { + cout << "捕获异常: " << e->getMsg() << endl; + delete e; // 手动释放内存 + } + + return 0; +} \ No newline at end of file diff --git a/day8/stl_code/d1.cpp b/day8/stl_code/d1.cpp new file mode 100644 index 0000000..2bc61ac --- /dev/null +++ b/day8/stl_code/d1.cpp @@ -0,0 +1,27 @@ +// stl 标准模板库开发 +// 初次使用: +// vector 存放基础类型的数据示例 +#include +#include +#include + +using namespace std; + +int main() +{ + vector v1; + v1.push_back(1); + v1.push_back(2); + v1.push_back(3); + v1.push_back(4); + v1.push_back(5); + v1.push_back(6); + + // 创建迭代器 + vector::iterator it; + for (it = v1.begin(); it != v1.end(); it++) + { + cout << *it << " "; + } + return 0; +} \ No newline at end of file diff --git a/day8/stl_code/d2.cpp b/day8/stl_code/d2.cpp new file mode 100644 index 0000000..a516696 --- /dev/null +++ b/day8/stl_code/d2.cpp @@ -0,0 +1,46 @@ +// 存放类对象的数据 vector +#include + +using namespace std; + +class Student +{ + friend ostream &operator<<(ostream &out, const Student &stu); + +private: + string name; + int age; + +public: + Student(const string &name, int age) + { + this->name = name; + this->age = age; + } +}; + +ostream &operator<<(ostream &out, const Student &stu) +{ + out << "name: " << stu.name << ", age: " << stu.age; + return out; +} + +int main() +{ + vector v; + v.push_back(Student("zhangsan", 20)); + v.push_back(Student("lisi", 21)); + v.push_back(Student("wangwu", 22)); + v.push_back(Student("zhaoliu", 23)); + + v.pop_back(); // 删除最后一个元素 + + // 创建迭代器 + vector::iterator it = v.end(); + while (it != v.begin()) + { + cout << *(--it) << endl; // 重载了<<运算符 + } + + return 0; +} diff --git a/day8/stl_code/d3.cpp b/day8/stl_code/d3.cpp new file mode 100644 index 0000000..81b1ade --- /dev/null +++ b/day8/stl_code/d3.cpp @@ -0,0 +1,48 @@ +// 基于 d3.cpp 的改进 +// vector 存放对象的指针 +#include + +using namespace std; + +class Student +{ + friend ostream &operator<<(ostream &out, const Student *stu); + +private: + string name; + int age; + +public: + Student(const string &name, int age) + { + this->name = name; + this->age = age; + } +}; + +ostream &operator<<(ostream &out, const Student *stu) +{ + out << "name: " << stu->name << ", age: " << stu->age; + return out; +} + +int main() +{ + vector v; + v.push_back(new Student("张三", 18)); + v.push_back(new Student("李四", 19)); + v.push_back(new Student("王五", 20)); + + v.pop_back(); // 删除最后一个元素 + + // 创建迭代器 + vector::iterator it = v.end(); + while (it != v.begin()) + { + it--; + cout << *it << endl; // 重载了<<运算符 + delete *it; // 释放空间 + } + + return 0; +} diff --git a/day8/stl_code/d4.cpp b/day8/stl_code/d4.cpp index f83c391..14ecd9b 100644 --- a/day8/stl_code/d4.cpp +++ b/day8/stl_code/d4.cpp @@ -5,6 +5,7 @@ using namespace std; int main() { + // 注意: vector > vs; 防止编辑器自动格式化为 >> vector > vs; // 嵌套容器 vector v1, v2, v3;