diff --git a/README.md b/README.md index 22ab20d..5a312dc 100644 --- a/README.md +++ b/README.md @@ -91,9 +91,9 @@ Book: https://sunrisepeak.github.io/d2ds // - 通过所有编译器检测 和 断言 // -#include +#include "common/common.hpp" -#include +#include "exercises/dslings.hpp" int main() { diff --git a/tests/common.hpp b/common/common.hpp similarity index 57% rename from tests/common.hpp rename to common/common.hpp index b5453bf..bc5d7dd 100644 --- a/tests/common.hpp +++ b/common/common.hpp @@ -2,16 +2,34 @@ #define __COMMON_HPP__D2DS #include +#include #include #include #include -#include +#define HONLY_LOGGER_TAG "D2DS" +#include "common/honly_logger.hpp" +#include "common/dslings_config.hpp" + + +#define d2ds_assert(expr) \ + if (!(expr)) { \ + HONLY_LOGW("❌ | %s", #expr); \ + } else { \ + HONLY_LOGI("✅ | %s", #expr); \ + } #define d2ds_assert_eq(a, b) \ -if (a != b) \ - std::cerr << #a << " == " << #b << " (" << a << " == " << b << ")" << std::endl; \ -assert((a) == (b)) + if (a != b) {\ + HONLY_LOGW("❌ | %s == %s (%s == %s)", \ + #a, #b, std::to_string(a).c_str(), std::to_string(b).c_str()); \ + } else {\ + HONLY_LOGI("✅ | %s == %s (%s == %s)", \ + #a, #b, std::to_string(a).c_str(), std::to_string(b).c_str()); \ + } + +#define D2DS_WAIT HONLY_LOGW("Delete the D2DS_WAIT to continue..."); + namespace d2ds { diff --git a/common/dslings_config.hpp b/common/dslings_config.hpp new file mode 100644 index 0000000..1d6df35 --- /dev/null +++ b/common/dslings_config.hpp @@ -0,0 +1,16 @@ +#ifndef __DSLINGS_CONFIG_HPP__D2DS +#define __DSLINGS_CONFIG_HPP__D2DS + +/* +// checker config +#define DSLINGS_0_CHECKER CHCKER_ENABLE +#define DSLINGS_1_CHECKER CHCKER_ENABLE +#define DSLINGS_2_CHECKER CHCKER_ENABLE +#define TEMPLATE_0_CHECKER CHCKER_ENABLE +#define TEMPLATE_1_CHECKER CHCKER_ENABLE +#define TEMPLATE_2_CHECKER CHCKER_ENABLE +#define CHCKER_ENABLE +#define CHCKER_PASS return 0; +*/ + +#endif \ No newline at end of file diff --git a/common/honly_logger.hpp b/common/honly_logger.hpp new file mode 100644 index 0000000..17af74c --- /dev/null +++ b/common/honly_logger.hpp @@ -0,0 +1,17 @@ +#ifndef __LOGGER_HPP__HONLY +#define __LOGGER_HPP__HONLY + +#include + +#ifndef HONLY_LOGGER_TAG +#define HONLY_LOGGER_TAG "HONLY" +#endif + +#define LOG_ENABLE true +#define _HONLY_LOG(fd, ...) if (LOG_ENABLE) fprintf (fd, __VA_ARGS__); fprintf (fd, "\033[0m\n") +#define HONLY_LOGI(...) fprintf (stdout, "\033[32m[%s LOGI]: \t%s: %s:%d - ", HONLY_LOGGER_TAG, __func__, __FILE__, __LINE__); _HONLY_LOG(stdout, __VA_ARGS__) +#define HONLY_LOGD(...) fprintf (stdout, "\033[37m[%s LOGD]: \t%s: %s:%d - ", HONLY_LOGGER_TAG, __func__, __FILE__, __LINE__); _HONLY_LOG(stdout, __VA_ARGS__) +#define HONLY_LOGW(...) fprintf (stdout, "\033[33m[%s LOGW]: \t%s: %s:%d - ", HONLY_LOGGER_TAG, __func__, __FILE__, __LINE__); _HONLY_LOG(stdout, __VA_ARGS__) +#define HONLY_LOGE(...) fprintf (stderr, "\033[31m[%s LOGE]: \t%s: %s:%d - ", HONLY_LOGGER_TAG, __func__, __FILE__, __LINE__); _HONLY_LOG(stderr, __VA_ARGS__) + +#endif \ No newline at end of file diff --git a/exercises/array/Array.hpp b/exercises/array/Array.hpp index 96bf8d7..d7cab5d 100644 --- a/exercises/array/Array.hpp +++ b/exercises/array/Array.hpp @@ -1,12 +1,16 @@ #ifndef __ARRAY_HPP__D2DS #define __ARRAY_HPP__D2DS -//#include - namespace d2ds { - //using dstruct::Array; -} +// show your code + +template +class Array { + +}; + +} #endif \ No newline at end of file diff --git a/exercises/dslings.hpp b/exercises/dslings.hpp index 860f256..cecbab7 100644 --- a/exercises/dslings.hpp +++ b/exercises/dslings.hpp @@ -8,7 +8,6 @@ namespace d2ds { -/* class MaxValue { public: MaxValue(int val) { @@ -29,8 +28,6 @@ class MaxValue { int __mMaxVal; }; -*/ - } #endif \ No newline at end of file diff --git a/exercises/other/cpp-base/RangeFor.hpp b/exercises/other/cpp-base/RangeFor.hpp new file mode 100644 index 0000000..1acddde --- /dev/null +++ b/exercises/other/cpp-base/RangeFor.hpp @@ -0,0 +1,43 @@ +#ifndef __RANGE_BASE_FOR_HPP__D2DS +#define __RANGE_BASE_FOR_HPP__D2DS + +#include + +namespace d2ds { +// show your code + +class py_range { +public: + py_range(int start, int end) : py_range(start, 1, end) { } + + py_range(int start, int step, int end) { + + __mLen = (end - start) / step; + + d2ds_assert(start < end); + d2ds_assert(step > 0); + d2ds_assert(__mLen <= 100); + + for (int i = 0; i < __mLen; i++) { + __mArr[i] = start; + start = start + step; + } + } + +public: + const int * begin() const { + return __mArr; + } + + const int * end() const { + return __mArr + __mLen; + } + +private: + int __mLen; + int __mArr[100]; +}; + +} + +#endif \ No newline at end of file diff --git a/exercises/other/cpp-base/Template.hpp b/exercises/other/cpp-base/Template.hpp new file mode 100644 index 0000000..45f8c9f --- /dev/null +++ b/exercises/other/cpp-base/Template.hpp @@ -0,0 +1,9 @@ +#ifndef __TEMPLATE_HPP__D2DS +#define __TEMPLATE_HPP__D2DS + +namespace d2ds { +// show your code + +} + +#endif \ No newline at end of file diff --git a/src/Instroduction.md b/src/Instroduction.md index 906c983..108d094 100644 --- a/src/Instroduction.md +++ b/src/Instroduction.md @@ -13,8 +13,8 @@ #### 代码示例 ```cpp -#include -#include +#include "common/common.hpp" +#include "exercises/dslings.hpp" int main() { @@ -226,9 +226,9 @@ Book: https://sunrisepeak.github.io/d2ds // - 通过所有编译器检测 和 断言 // -#include +#include "common/common.hpp" -#include +#include "exercises/dslings.hpp" int main() { diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 57554b3..b9c2ac2 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -3,23 +3,25 @@ # 阅读准备 - [导读](./Instroduction.md) -# 线性数据结构 +# 常用数据结构 - [数组]() - [Array数组]() - [Vector动态数组]() - [链表]() - - [静态单链表]() - - [静态双链表]() + - [嵌入式单链表]() - [单链表]() + - [嵌入式双链表]() - [双链表]() + - [静态链表]() - [栈]() - - [最值栈]() - - [单调栈]() + - [栈适配器]() - [队列]() + - [队列适配器]() - [双端队列]() + - [循环队列]() # 非线性数据结构 @@ -29,9 +31,12 @@ - [图]() - # 相关主题 -- [数据结构基本概念](./chapter_0.md) -- [C++基础]() +- [数据结构基本概念](other/0_ds_base.md) +- [C++基础](other/1_cpp_base.md) + - [范型编程](other/1_cpp_base.template.md) + - [范围for循环语法糖](other/2_cpp_base.rangefor.md) - [内存管理]() -- [迭代器设计模式]() \ No newline at end of file +- [设计模式]() + - [迭代器设计模式]() + - [适配器设计模式]() \ No newline at end of file diff --git a/src/chapter_0.md b/src/other/0_ds_base.md similarity index 100% rename from src/chapter_0.md rename to src/other/0_ds_base.md diff --git a/src/other/1_cpp_base.md b/src/other/1_cpp_base.md new file mode 100644 index 0000000..b3e1e1a --- /dev/null +++ b/src/other/1_cpp_base.md @@ -0,0 +1,2 @@ +# C++ 基础 + diff --git a/src/other/1_cpp_base.template.md b/src/other/1_cpp_base.template.md new file mode 100644 index 0000000..4568575 --- /dev/null +++ b/src/other/1_cpp_base.template.md @@ -0,0 +1,195 @@ +# template | 模板 : 范型编程初识 + +**范型编程**是一种**代码生成技术**, 它能帮助我们节省写大量重复代码的时间。例如, 在我们实现数据结构的时候, 使用**范型编程**技术可以让我们写一套代码就能应用到多种类型的效果。当然, 要想深度掌握**范型编程**技术不是一个简单的事情, 它的难度不亚于学习一门新的语言。 但是幸运的是在[**d2ds**](https://sunrisepeak.github.io/d2ds/)中我们只涉及其最基础的部分, 下面我们将来简单的介绍它们。 + + +## 函数模板 - max + +实现`d2ds::max`函数, 实现获取两个a和b变量中的最大值 + +```cpp +// template.0.cpp - readonly +// +// 描述: +// 实现max函数模板 +// +// 目标/要求: +// - 不修改该代码检测文件 +// - 在exercises/other/cpp-base/Template.hpp中完成你的代码设计 +// - 通过所有断言检测 +// + +#include + +#include "common/common.hpp" + +#include "exercises/other/cpp-base/Template.hpp" + +int main() { + { // int + int a = -1, b = 1; + d2ds_assert_eq(d2ds::max(a, b), dstruct::max(a, b)); + } + + { // unsigned int + unsigned int a = 4294967295, b = 1; + d2ds_assert_eq(d2ds::max(a, b), dstruct::max(a, b)); + } + + { // double + double a = 1.3, b = 3.1; + d2ds_assert_eq(d2ds::max(a, b), dstruct::max(a, b)); + } + + return 0; +} +``` + +### max函数 - 重载版本实现 + +通过C++的函数**重载技术(overload)**, 我们分别对`int` | `unsigned int` | `double` 类型版本的max进行实现 + +```c++ +int max(int a, int b) { + return a > b ? a : b; +} + +unsigned int max(unsigned int a, unsigned int b) { + return a > b ? a : b; +} + +double max(double a, double b) { + return a > b ? a : b; +} +``` + +这里通过观察**max函数**这三个类型的实现, 可以轻易感觉到它们只有参数和返回值类型不一样, 而函数体的代码都是一样的。此时的需求开发越多, 就会让开发者产生在做**重复工作**的感觉。部分想"偷懒"的程序员, 可能会借助IDE来设置代码模板来减轻工作量。幸运由于大多数程序员对这种"偷懒"的必要性达成了共识, 这促使了多数的编程语言对**范型编程|模板**做了支持, 在C++中对应的就是`template`。 + +### max函数 - 函数模板版本实现 + +通过函数模板, 可以写一套代码实现上面(重载实现)三套代码的效果 + +```c++ +template +T max(T a, T b) { + return a > b ? a : b; +} +``` + +| 标识 | 解释 | +| - | - | +| `template` | 模板标识 | +| `<>` | 范形参数类型列表(可以有多个参数) | +| `typename T` | `typename`为类型名修饰符, 后面跟着类型名标识`T` | + +在数据结构实现中使用模板技术 +- **第一个好处:** 只需要实现一套代码逻辑实现就可以支撑多种类型 +- **第二个好处:** 编译器在编译期只会对使用到的类型做模板实例化, 对于没有用到的类型不会进行代码生成 + +如当只使用`int` 和 `double` 类型时: + +```cpp +d2ds::max(1, 2); +d2ds::max(1.1, 0.8); +``` + +编译器通过按需进行代码生成来减少代码量, 只会实例化出如下两个版本: + +```cpp +int max(int a, int b) { + return a > b ? a : b; +} + +double max(double a, double b) { + return a > b ? a : b; +} +``` + +> 注: 模板的代码生成技术在特定情况下, 也可能造成代码膨胀(code bloat)的问题 + +## 类模板 - Box + +实现`d2ds::Box`用于存储指定类型的值 + +```cpp +// template.2.cpp - readonly +// +// 描述: +// 实现Box类模板, 来存储指定类型的值 +// +// 目标/要求: +// - 不修改该代码检测文件 +// - 在exercises/other/cpp-base/Template.hpp中完成你的代码设计 +// - 通过所有断言检测 +// + +#include + +#include "common/common.hpp" + +#include "exercises/other/cpp-base/Template.hpp" + + +int main() { + { + d2ds::Box box; + box.set_value(2); + d2ds_assert_eq(box.get_value(), 2); + } + + { + d2ds::Box box; + box.set_value("Hello, d2ds!"); + d2ds_assert(box.get_value() == dstruct::String("Hello, d2ds!")); + } + + D2DS_WAIT + + return 0; +} +``` + +### Box类模板 - 类型定义 + +```cpp +d2ds::Box intBox; +d2ds::Box stringBox; +``` + +类模板的定义和函数模板的定义是类似的, 都是在类名(函数签名)前使用`template`进行标识 + +```cpp +template +class Box { + +}; +``` + +### Box类模板 - 具体实现 + +在类模板的作用域中, 可以直接把类型`T`当成一个正常的类型符号使用以及用它来完成对应的代码实现 + +```cpp +template +class Box { +public: + Box() : __mVal{} { } + + T get_value() const { + return __mVal; + } + + void set_value(const T &val) { + __mVal = val; + } + +private: + T __mVal; +}; +``` + +在Box的实现中, 使用`T __mVal;`定义了一个存储用户指定类型值的成员变量。并且在`get_value`和`set_value`成员函数中也像使用正常的类型一样使用**类型名`T`**。它是一个未确定的类型的标识符, 在编译期编译器将会根据使用者指定的类型来去实例化出对应的版本, 就像上面函数模板一样。总之, 在编写模板代码的时候我们可以把`T`当成一个**未知类型名**, 像正常大多数类型名的用法一样来使用它。 + +## 总结 + +本小节介绍了C++中**范型编程**中最基础和常用的两个部分 -- **函数模板**和**类模板**的定义方法。通过使用模板的编译器**代码生成**可以让我们设计的数据结构支持多种类型, 而又不用编写多份代码。如果你已经掌握了本节内容, 那就快去到数据结构实现的部分去实际使用C++的范型编程技术吧。 \ No newline at end of file diff --git a/src/other/2_cpp_base.rangefor.md b/src/other/2_cpp_base.rangefor.md new file mode 100644 index 0000000..8e1b9e2 --- /dev/null +++ b/src/other/2_cpp_base.rangefor.md @@ -0,0 +1,127 @@ +# 语法糖 | 范围for循环 + +C++从C++11开始也像很多语言一样提供了范围for循环这个"语法糖"。它是用作对范围中的各个值(如容器中的所有元素)进行操作的较传统for循环更加可读的等价版本。下面我以`std::vector`为例对比并演示一下它的使用: + +**使用普通for循环** + +通过`std::vector`的`begin`和`end`迭代器来获取数据结构(容器)中存储的数据。 其中**迭代器`it`**的行为很像指针, 可以通过*号去"解引用"获取数据, 通过`++`让迭代器指向存储的下一个数据。 + +```cpp +#include + +int main() { + std::vector vec { 1, 2, 3, 4 }; + + int val; + for (auto it = vec.begin(); it != vec.end(); it++) { + val = *it; + //... + } + + return 0; +} +``` + +**使用范围for循环** + +通过使用范围for循环简化了对数据结构中数据的访问, 不需要开发者直接去控制和判断迭代器就可以轻松访问到所有数据。这里需要注意的是 —— 其实这个简化了的for循环的本质也是像上面一样使用了迭代器的设计模式, 只是编译器帮我们省去了关于迭代器的相关操作, 原理上可视为等价的。 + +```cpp +#include + +int main() { + std::vector vec { 1, 2, 3, 4 }; + + for (int val : vec) { + // ... + } + + return 0; +} +``` + +## 自定义类型如何支持这个语法糖? + +对于库开发者, 比起使用这个范围for循环, 更让其好奇和兴奋的是 —— **如何让自己写的数据结构也能支持这么好的性质, 这样大家用起来就会更爽了(这可能就是传说中的大家好才是真的好哈哈)**。下面将讨论自定义类型如何支持这个范围for语法糖。 + +这里引用一下[cppreference](https://en.cppreference.com)上对它的解释 + +```cpp +// https://en.cppreference.com/w/cpp/language/range-for +{ // until C++17 + auto && __range = range-expression ; + for (auto __begin = begin-expr, __end = end-expr; __begin != __end; ++__begin) + { + range-declaration = *__begin; + loop-statement + } +} +``` + +为了更好的观察, 我们还是以上面`std::vector`的范围for作为例子, 给出编译对这个语法套进行代码展开的**可能实现** + +```cpp +{ // 没有展开的形式 + for (int val : vec) { + // ... + } +} +{ // 编译器代码展开的可能实现 + auto && __range = vec; + for (auto __begin = __range.begin(), __end = __range.end(); __begin != __end; ++__begin) { + auto && val = *__begin; + // ... + } +} +{ // 编译器代码展开的可能实现 -- 易读版 + auto __end = vec.end(); + for (auto it = vec.begin(); it != __end; ++it) { + int val = *it; + // ... + } +} +``` + +从简化的`易读版`上可以看出, 和前面最开始的普通版本的for循环实现是差不多的, 并且我们可以总结出如下要素: + +- 1.需要实现`begin()` +- 2.需要实现`end()` +- 3.`begin()` / `end()` 返回的类型需要具备指针的行为操作(或者至少要满足`*`和`++`操作) + +下面我就以一个例子的实现来具体阐述和感受**自定类型**支持范围for的完成过程 + +## 仿Python中range实现 - py_range + +```cpp +class py_range { +public: + py_range(int start, int end) : py_range(start, 1, end) { } + + py_range(int start, int step, int end) { + + __mLen = (end - start) / step; + + d2ds_assert(start < end); + d2ds_assert(step > 0); + d2ds_assert(__mLen <= 100); + + for (int i = 0; i < __mLen; i++) { + __mArr[i] = start; + start = start + step; + } + } + +public: + const int * begin() const { + return __mArr; + } + + const int * end() const { + return __mArr + __mLen; + } + +private: + int __mLen; + int __mArr[100]; +}; +``` \ No newline at end of file diff --git a/tests/array/array.0.cpp b/tests/array/array.0.cpp index 1523ef7..fcb4665 100644 --- a/tests/array/array.0.cpp +++ b/tests/array/array.0.cpp @@ -1,9 +1,20 @@ -#include +// array.0.cpp - readonly +// +// 描述: +// 实现Array数据结构可以存储开发者指定类型的功能 +// +// 目标/要求: +// - 不修改该代码检测文件 +// - 在exercises/array/Array.hpp中完成你的代码设计 +// - 通过Array类型定义的编译器检测 +// + +#include "common/common.hpp" #include int main() { d2ds::Array intArr; - printf("Hello Array!\n"); + d2ds::Array doubleArr; return 0; } \ No newline at end of file diff --git a/tests/array/array.1.cpp b/tests/array/array.1.cpp index a9bec9c..7bf13d2 100644 --- a/tests/array/array.1.cpp +++ b/tests/array/array.1.cpp @@ -1,4 +1,4 @@ -#include +#include "common/common.hpp" #include diff --git a/tests/array/array.2.cpp b/tests/array/array.2.cpp index a9bec9c..7bf13d2 100644 --- a/tests/array/array.2.cpp +++ b/tests/array/array.2.cpp @@ -1,4 +1,4 @@ -#include +#include "common/common.hpp" #include diff --git a/tests/dslings.0.cpp b/tests/dslings.0.cpp index 2fcab21..62820c5 100644 --- a/tests/dslings.0.cpp +++ b/tests/dslings.0.cpp @@ -11,9 +11,9 @@ // - 通过所有编译器检测 和 断言 // -#include +#include "common/common.hpp" -#include +#include "exercises/dslings.hpp" int main() { diff --git a/tests/dslings.1.cpp b/tests/dslings.1.cpp index 0e13ce7..67ed1ce 100644 --- a/tests/dslings.1.cpp +++ b/tests/dslings.1.cpp @@ -11,9 +11,9 @@ // - 通过所有编译器检测 和 断言 // -#include +#include "common/common.hpp" -#include +#include "exercises/dslings.hpp" int main() { diff --git a/tests/dslings.2.cpp b/tests/dslings.2.cpp index 912c6b0..fdc4c3c 100644 --- a/tests/dslings.2.cpp +++ b/tests/dslings.2.cpp @@ -11,8 +11,10 @@ // - 通过所有编译器检测 和 断言 // -#include -#include +#include + +#include "common/common.hpp" +#include "exercises/dslings.hpp" int main() { @@ -41,5 +43,7 @@ int main() { d2ds_assert_eq(mVal.get(), maxVal); + //D2DS_WAIT + return 0; } \ No newline at end of file diff --git a/tests/other/cpp-base/range_for.0.cpp b/tests/other/cpp-base/range_for.0.cpp new file mode 100644 index 0000000..dd97f41 --- /dev/null +++ b/tests/other/cpp-base/range_for.0.cpp @@ -0,0 +1,21 @@ +// range_for.0.cpp - readonly +// +// 描述: +// 实现py_range的类型定义 +// +// 目标/要求: +// - 不修改该代码检测文件 +// - 在exercises/other/cpp-base/RangeFor.hpp中完成你的代码设计 +// + +#include + +#include "common/common.hpp" + +#include "exercises/other/cpp-base/RangeFor.hpp" + +int main() { + d2ds::py_range(0, 10); + d2ds::py_range(0, 5, 200); + return 0; +} \ No newline at end of file diff --git a/tests/other/cpp-base/range_for.1.cpp b/tests/other/cpp-base/range_for.1.cpp new file mode 100644 index 0000000..bca7244 --- /dev/null +++ b/tests/other/cpp-base/range_for.1.cpp @@ -0,0 +1,30 @@ +// range_for.1.cpp - readonly +// +// 描述: +// 实现py_range的begin和end +// +// 目标/要求: +// - 不修改该代码检测文件 +// - 在exercises/other/cpp-base/Template.hpp中完成你的代码设计 +// - 通过所有断言检测 +// + +#include + +#include "common/common.hpp" + +#include "exercises/other/cpp-base/RangeFor.hpp" + +int main() { + d2ds::py_range range(2, 10); + + auto __begin = range.begin(); + auto __end = range.end(); + + d2ds_assert_eq(*__begin, 2); + d2ds_assert(__begin != __end); + + D2DS_WAIT + + return 0; +} \ No newline at end of file diff --git a/tests/other/cpp-base/template.0.cpp b/tests/other/cpp-base/template.0.cpp new file mode 100644 index 0000000..d5e6021 --- /dev/null +++ b/tests/other/cpp-base/template.0.cpp @@ -0,0 +1,42 @@ +// template.0.cpp - readonly +// +// 描述: +// 实现max函数模板 +// +// 目标/要求: +// - 不修改该代码检测文件 +// - 在exercises/other/cpp-base/Template.hpp中完成你的代码设计 +// - 通过所有断言检测 +// + +#include + +#include "common/common.hpp" + +#include "exercises/other/cpp-base/Template.hpp" + +int main() { + + { // int + int a = -1, b = 1; + d2ds_assert_eq(d2ds::max(a, b), dstruct::max(a, b)); + } + + { // unsigned int + unsigned int a = 4294967295, b = 1; + d2ds_assert_eq(d2ds::max(a, b), dstruct::max(a, b)); + } + + { // double + double a = 1.3, b = 3.1; + d2ds_assert_eq(d2ds::max(a, b), dstruct::max(a, b)); + } + + int arr[] = {3, 4, 5, 6}; + + for (int val : arr) { + std::cout << val << std::endl; + } + + return 0; +} \ No newline at end of file diff --git a/tests/other/cpp-base/template.1.cpp b/tests/other/cpp-base/template.1.cpp new file mode 100644 index 0000000..4a861e7 --- /dev/null +++ b/tests/other/cpp-base/template.1.cpp @@ -0,0 +1,24 @@ +// template.1.cpp - readonly +// +// 描述: +// 实现Box类模板 - 范型支持 +// +// 目标/要求: +// - 不修改该代码检测文件 +// - 在exercises/other/cpp-base/Template.hpp中完成你的代码设计 +// - 通过所有编译器检查 +// + +#include + +#include "common/common.hpp" + +#include "exercises/other/cpp-base/Template.hpp" + + +int main() { + + d2ds::Box intBox; + d2ds::Box stringBox; + return 0; +} \ No newline at end of file diff --git a/tests/other/cpp-base/template.2.cpp b/tests/other/cpp-base/template.2.cpp new file mode 100644 index 0000000..d763701 --- /dev/null +++ b/tests/other/cpp-base/template.2.cpp @@ -0,0 +1,36 @@ +// template.2.cpp - readonly +// +// 描述: +// 实现Box类模板, 来存储指定类型的值 +// +// 目标/要求: +// - 不修改该代码检测文件 +// - 在exercises/other/cpp-base/Template.hpp中完成你的代码设计 +// - 通过所有断言检测 +// + +#include + +#include "common/common.hpp" + +#include "exercises/other/cpp-base/Template.hpp" + + +int main() { + + { + d2ds::Box box; + box.set_value(2); + d2ds_assert_eq(box.get_value(), 2); + } + + { + d2ds::Box box; + box.set_value("Hello, d2ds!"); + d2ds_assert(box.get_value() == dstruct::String("Hello, d2ds!")); + } + + D2DS_WAIT + + return 0; +} \ No newline at end of file diff --git a/xmake.lua b/xmake.lua index 2597c77..41d7ca4 100644 --- a/xmake.lua +++ b/xmake.lua @@ -18,11 +18,31 @@ target("0.dslings-2") set_kind("binary") add_files("tests/dslings.2.cpp") -target("1.array-0") +target("1.template-0") + set_kind("binary") + add_files("tests/other/cpp-base/template.0.cpp") + +target("1.template-1") + set_kind("binary") + add_files("tests/other/cpp-base/template.1.cpp") + +target("1.template-2") + set_kind("binary") + add_files("tests/other/cpp-base/template.2.cpp") + +target("2.range_for-0") + set_kind("binary") + add_files("tests/other/cpp-base/range_for.0.cpp") + +target("2.range_for-1") + set_kind("binary") + add_files("tests/other/cpp-base/range_for.1.cpp") + +target("3.array-0") set_kind("binary") add_files("tests/array/array.0.cpp") -target("1.array-1") +target("3.array-1") set_kind("binary") add_files("tests/array/array.1.cpp") @@ -33,6 +53,17 @@ task("dslings") import("core.project.target") import("core.base.global") + local checker_pass = false + + local dslings_checker_pass_config = { + ["0.dslings-0"] = checker_pass, + ["0.dslings-1"] = checker_pass, + ["0.dslings-2"] = checker_pass, + ["1.template-0"] = checker_pass, + ["1.template-1"] = checker_pass, + ["1.template-2"] = checker_pass, + } + local function get_len(pairs_type) length = 0 for _, _ in pairs_type do @@ -49,7 +80,7 @@ task("dslings") end end - local function print_info(target_name, built_targets, total_targets, current_file_path, output, success) + local function print_info(target_name, built_targets, total_targets, current_file_path, output, status) clear_screen() @@ -68,7 +99,7 @@ task("dslings") print(string.format("\n[Target: %s]\n", target_name)) -- print status - if success then + if status then print(string.format("✅ Successfully ran %s!", current_file_path)) print("\n🎉 The code is compiling! 🎉\n") else @@ -129,7 +160,6 @@ task("dslings") function (e) output = e build_success = false - sleep_sec = 1000 * 3 end } } @@ -137,24 +167,40 @@ task("dslings") if build_success then try { function () - os.iorunv("xmake", {"r", name}) + output, _ = os.iorunv("xmake", {"r", name}) end, catch { function (e) output = e build_success = false - sleep_sec = 1000 * 3 end } } end + local status = build_success + + if dslings_checker_pass_config[name] == true then + build_success = true + else + if type(output) == "string" then + if string.find(output, "❌") then + status = false + build_success = false + elseif string.find(output, "D2DS_WAIT") then + build_success = false + end + end + end + if build_success then built_targets = built_targets + 1 + else + sleep_sec = 1000 * 2 end - print_info(name, built_targets, total_targets, relative_path, output, build_success) + print_info(name, built_targets, total_targets, relative_path, output, status) output = "" os.sleep(sleep_sec)