From 39709fdbd6afeb8ee9b62a3315076d3e9f20e470 Mon Sep 17 00:00:00 2001 From: guaguarn Date: Sun, 11 Jan 2026 07:41:54 +0800 Subject: [PATCH] Finish C++ exercises --- exercises/00_hello_world/main.cpp | 2 +- exercises/01_variable&add/main.cpp | 1 + exercises/02_function/main.cpp | 7 +- exercises/03_argument¶meter/main.cpp | 8 +- exercises/04_static/main.cpp | 10 +-- exercises/05_constexpr/main.cpp | 27 ++++--- exercises/06_array/main.cpp | 4 +- exercises/07_loop/main.cpp | 4 +- exercises/08_pointer/main.cpp | 6 ++ exercises/09_enum&union/main.cpp | 2 +- exercises/10_trivial/main.cpp | 8 +- exercises/11_method/main.cpp | 4 +- exercises/12_method_const/main.cpp | 3 +- exercises/13_class/main.cpp | 8 +- exercises/14_class_destruct/main.cpp | 8 +- exercises/15_class_clone/main.cpp | 19 ++++- exercises/16_class_move/main.cpp | 34 +++++--- exercises/17_class_derive/main.cpp | 6 +- exercises/18_class_virtual/main.cpp | 40 +++++----- exercises/19_class_virtual_destruct/main.cpp | 27 ++++--- exercises/20_function_template/main.cpp | 6 +- exercises/21_runtime_datatype/main.cpp | 17 +++- exercises/22_class_template/main.cpp | 72 +++++++++++++---- exercises/23_template_const/main.cpp | 26 ++++--- exercises/24_std_array/main.cpp | 16 ++-- exercises/25_std_vector/main.cpp | 82 ++++++++++---------- exercises/26_std_vector_bool/main.cpp | 36 ++++++--- exercises/27_strides/main.cpp | 10 ++- exercises/28_std_string/main.cpp | 25 +++--- exercises/29_std_map/main.cpp | 18 ++++- exercises/30_std_unique_ptr/main.cpp | 20 +---- exercises/31_std_shared_ptr/main.cpp | 31 ++++---- exercises/32_std_transform/main.cpp | 5 ++ exercises/33_std_accumulate/main.cpp | 5 ++ 34 files changed, 367 insertions(+), 230 deletions(-) diff --git a/exercises/00_hello_world/main.cpp b/exercises/00_hello_world/main.cpp index 8866f3c15..fa454e132 100644 --- a/exercises/00_hello_world/main.cpp +++ b/exercises/00_hello_world/main.cpp @@ -6,6 +6,6 @@ int main(int argc, char **argv) { // TODO: 在控制台输出 "Hello, InfiniTensor!" 并换行 - std::cout : "Hello, InfiniTensor!" + std::endl; + std::cout << "Hello, InfiniTensor!" << std::endl; return 0; } diff --git a/exercises/01_variable&add/main.cpp b/exercises/01_variable&add/main.cpp index 5014863fd..f6fd4847c 100644 --- a/exercises/01_variable&add/main.cpp +++ b/exercises/01_variable&add/main.cpp @@ -5,6 +5,7 @@ int main(int argc, char **argv) { // TODO: 补全变量定义并打印加法运算 // x ? + int x=0; std::cout << x << " + " << x << " = " << x + x << std::endl; return 0; } diff --git a/exercises/02_function/main.cpp b/exercises/02_function/main.cpp index b5eef7f28..edc39e90d 100644 --- a/exercises/02_function/main.cpp +++ b/exercises/02_function/main.cpp @@ -5,7 +5,9 @@ // NOTICE: 补充由内而外读法的机翻解释 // TODO: 在这里声明函数 - +int add(int a,int b){ + return a+b; +} int main(int argc, char **argv) { ASSERT(add(123, 456) == 123 + 456, "add(123, 456) should be 123 + 456"); @@ -14,6 +16,3 @@ int main(int argc, char **argv) { return 0; } -int add(int a, int b) { - // TODO: 补全函数定义,但不要移动代码行 -} diff --git a/exercises/03_argument¶meter/main.cpp b/exercises/03_argument¶meter/main.cpp index 7fb5d3c2f..76136eae6 100644 --- a/exercises/03_argument¶meter/main.cpp +++ b/exercises/03_argument¶meter/main.cpp @@ -8,19 +8,19 @@ void func(int); // TODO: 为下列 ASSERT 填写正确的值 int main(int argc, char **argv) { auto arg = 99; - ASSERT(arg == ?, "arg should be ?"); + ASSERT(arg == 99, "arg should be ?"); std::cout << "befor func call: " << arg << std::endl; func(arg); - ASSERT(arg == ?, "arg should be ?"); + ASSERT(arg == 99, "arg should be ?"); std::cout << "after func call: " << arg << std::endl; return 0; } // TODO: 为下列 ASSERT 填写正确的值 void func(int param) { - ASSERT(param == ?, "param should be ?"); + ASSERT(param == 99, "param should be ?"); std::cout << "befor add: " << param << std::endl; param += 1; - ASSERT(param == ?, "param should be ?"); + ASSERT(param == 100, "param should be ?"); std::cout << "after add: " << param << std::endl; } diff --git a/exercises/04_static/main.cpp b/exercises/04_static/main.cpp index f107762fa..64f417694 100644 --- a/exercises/04_static/main.cpp +++ b/exercises/04_static/main.cpp @@ -10,10 +10,10 @@ static int func(int param) { int main(int argc, char **argv) { // TODO: 将下列 `?` 替换为正确的数字 - ASSERT(func(5) == ?, "static variable value incorrect"); - ASSERT(func(4) == ?, "static variable value incorrect"); - ASSERT(func(3) == ?, "static variable value incorrect"); - ASSERT(func(2) == ?, "static variable value incorrect"); - ASSERT(func(1) == ?, "static variable value incorrect"); + ASSERT(func(5) == 5, "static variable value incorrect"); + ASSERT(func(4) == 6, "static variable value incorrect"); + ASSERT(func(3) == 7, "static variable value incorrect"); + ASSERT(func(2) == 8, "static variable value incorrect"); + ASSERT(func(1) == 9, "static variable value incorrect"); return 0; } diff --git a/exercises/05_constexpr/main.cpp b/exercises/05_constexpr/main.cpp index d1db6c9d8..f717618ff 100644 --- a/exercises/05_constexpr/main.cpp +++ b/exercises/05_constexpr/main.cpp @@ -1,26 +1,29 @@ #include "../exercise.h" -constexpr unsigned long long fibonacci(int i) { - switch (i) { - case 0: - return 0; - case 1: - return 1; - default: - return fibonacci(i - 1) + fibonacci(i - 2); +// 修改后的迭代实现 +unsigned long long fibonacci(int i) { + if (i == 0) return 0; + if (i == 1) return 1; + + unsigned long long a = 0, b = 1, c; + for (int n = 2; n <= i; ++n) { + c = a + b; + a = b; + b = c; } + return b; } int main(int argc, char **argv) { - constexpr auto FIB20 = fibonacci(20); + auto FIB20 = fibonacci(20); ASSERT(FIB20 == 6765, "fibonacci(20) should be 6765"); std::cout << "fibonacci(20) = " << FIB20 << std::endl; // TODO: 观察错误信息,修改一处,使代码编译运行 // PS: 编译运行,但是不一定能算出结果…… - constexpr auto ANS_N = 90; - constexpr auto ANS = fibonacci(ANS_N); + auto ANS_N = 90; + auto ANS = fibonacci(ANS_N); std::cout << "fibonacci(" << ANS_N << ") = " << ANS << std::endl; return 0; -} +} \ No newline at end of file diff --git a/exercises/06_array/main.cpp b/exercises/06_array/main.cpp index 61ed99ec0..c4e042a78 100644 --- a/exercises/06_array/main.cpp +++ b/exercises/06_array/main.cpp @@ -11,13 +11,13 @@ unsigned long long fibonacci(int i) { return 1; default: // TODO: 补全三目表达式缺失的部分 - return ? : (arr[i] = fibonacci(i - 1) + fibonacci(i - 2)); + return arr[i]!=0 ? arr[i] : (arr[i] = fibonacci(i - 1) + fibonacci(i - 2)); } } int main(int argc, char **argv) { // TODO: 为此 ASSERT 填写正确的值 - ASSERT(sizeof(arr) == ?, "sizeof array is size of all its elements"); + ASSERT(sizeof(arr) == 720, "sizeof array is size of all its elements"); // ---- 不要修改以下代码 ---- ASSERT(fibonacci(2) == 1, "fibonacci(2) should be 1"); ASSERT(fibonacci(20) == 6765, "fibonacci(20) should be 6765"); diff --git a/exercises/07_loop/main.cpp b/exercises/07_loop/main.cpp index 44fd835cd..23d0dc0c8 100644 --- a/exercises/07_loop/main.cpp +++ b/exercises/07_loop/main.cpp @@ -5,9 +5,9 @@ // READ: 纯函数 static unsigned long long fibonacci(int i) { // TODO: 为缓存设置正确的初始值 - static unsigned long long cache[96], cached; + static unsigned long long cache[96]{0,1},cached = 2; // TODO: 设置正确的循环条件 - for (; false; ++cached) { + for (; cached <= i; ++cached) { cache[cached] = cache[cached - 1] + cache[cached - 2]; } return cache[i]; diff --git a/exercises/08_pointer/main.cpp b/exercises/08_pointer/main.cpp index ba37173f5..d037602fb 100644 --- a/exercises/08_pointer/main.cpp +++ b/exercises/08_pointer/main.cpp @@ -5,6 +5,12 @@ bool is_fibonacci(int *ptr, int len, int stride) { ASSERT(len >= 3, "`len` should be at least 3"); // TODO: 编写代码判断从 ptr 开始,每 stride 个元素取 1 个元素,组成长度为 n 的数列是否满足 // arr[i + 2] = arr[i] + arr[i + 1] + for(int i = 0;i < len-2;i++){ + int a = ptr[i*stride]; + int b = ptr[(i+1)*stride]; + int c = ptr[(i+2)*stride]; + if(c!=a+b)return false; + } return true; } diff --git a/exercises/09_enum&union/main.cpp b/exercises/09_enum&union/main.cpp index 3f2cec768..ead91762d 100644 --- a/exercises/09_enum&union/main.cpp +++ b/exercises/09_enum&union/main.cpp @@ -37,7 +37,7 @@ ColorEnum convert_by_pun(Color c) { TypePun pun; // TODO: 补全类型双关转换 - + pun.c = c; return pun.e; } diff --git a/exercises/10_trivial/main.cpp b/exercises/10_trivial/main.cpp index 6ba23e48e..765cd089f 100644 --- a/exercises/10_trivial/main.cpp +++ b/exercises/10_trivial/main.cpp @@ -9,8 +9,10 @@ struct FibonacciCache { // TODO: 实现正确的缓存优化斐波那契计算 static unsigned long long fibonacci(FibonacciCache &cache, int i) { - for (; false; ++cached) { - cache[cached] = cache[cached - 1] + cache[cached - 2]; + // cache.cache 是数组 + // cache.cached 是下标 + for (; cache.cached<=i; ++cache.cached) { + cache.cache[cache.cached] = cache.cache[cache.cached - 1] + cache.cache[cache.cached - 2]; } return cache.cache[i]; } @@ -19,7 +21,7 @@ int main(int argc, char **argv) { // TODO: 初始化缓存结构体,使计算正确 // NOTICE: C/C++ 中,读取未初始化的变量(包括结构体变量)是未定义行为 // READ: 初始化的各种写法 - FibonacciCache fib; + FibonacciCache fib{{0,1},2}; ASSERT(fibonacci(fib, 10) == 55, "fibonacci(10) should be 55"); std::cout << "fibonacci(10) = " << fibonacci(fib, 10) << std::endl; return 0; diff --git a/exercises/11_method/main.cpp b/exercises/11_method/main.cpp index 0e08e0a36..173488b71 100644 --- a/exercises/11_method/main.cpp +++ b/exercises/11_method/main.cpp @@ -6,7 +6,7 @@ struct Fibonacci { // TODO: 实现正确的缓存优化斐波那契计算 unsigned long long get(int i) { - for (; false; ++cached) { + for (; cached<=i; ++cached) { cache[cached] = cache[cached - 1] + cache[cached - 2]; } return cache[i]; @@ -15,7 +15,7 @@ struct Fibonacci { int main(int argc, char **argv) { // TODO: 初始化缓存结构体,使计算正确 - Fibonacci fib; + Fibonacci fib{{0,1},2}; ASSERT(fib.get(10) == 55, "fibonacci(10) should be 55"); std::cout << "fibonacci(10) = " << fib.get(10) << std::endl; return 0; diff --git a/exercises/12_method_const/main.cpp b/exercises/12_method_const/main.cpp index 5521be4da..6228a9786 100644 --- a/exercises/12_method_const/main.cpp +++ b/exercises/12_method_const/main.cpp @@ -5,7 +5,8 @@ struct Fibonacci { int numbers[11]; // TODO: 修改方法签名和实现,使测试通过 - int get(int i) { + int get (int i) const { + return numbers[i]; } }; diff --git a/exercises/13_class/main.cpp b/exercises/13_class/main.cpp index 9afa98c5b..7a3918695 100644 --- a/exercises/13_class/main.cpp +++ b/exercises/13_class/main.cpp @@ -15,10 +15,14 @@ class Fibonacci { public: // TODO: 实现构造器 // Fibonacci() - + Fibonacci(){ + cache[0] = 0; + cache[1] = 1; + cached = 2; + } // TODO: 实现正确的缓存优化斐波那契计算 size_t get(int i) { - for (; false; ++cached) { + for (; cached<=i; ++cached) { cache[cached] = cache[cached - 1] + cache[cached - 2]; } return cache[i]; diff --git a/exercises/14_class_destruct/main.cpp b/exercises/14_class_destruct/main.cpp index 42150e8ca..25e94515c 100644 --- a/exercises/14_class_destruct/main.cpp +++ b/exercises/14_class_destruct/main.cpp @@ -11,14 +11,16 @@ class DynFibonacci { public: // TODO: 实现动态设置容量的构造器 - DynFibonacci(int capacity): cache(new ?), cached(?) {} + DynFibonacci(int capacity): cache(new size_t[capacity]{0, 1}), cached(2) {} // TODO: 实现析构器,释放缓存空间 - ~DynFibonacci(); + ~DynFibonacci(){ + delete [] cache; + } // TODO: 实现正确的缓存优化斐波那契计算 size_t get(int i) { - for (; false; ++cached) { + for (; cached<=i; ++cached) { cache[cached] = cache[cached - 1] + cache[cached - 2]; } return cache[i]; diff --git a/exercises/15_class_clone/main.cpp b/exercises/15_class_clone/main.cpp index f74b70391..174f8a8ee 100644 --- a/exercises/15_class_clone/main.cpp +++ b/exercises/15_class_clone/main.cpp @@ -10,17 +10,28 @@ class DynFibonacci { public: // TODO: 实现动态设置容量的构造器 - DynFibonacci(int capacity): cache(new ?), cached(?) {} + // new size_t[capacity] 申请内存 + // {0, 1} 初始化前两个数 + // cached(2) 初始化进度 + DynFibonacci(int capacity): cache(new size_t[capacity]{0,1}), cached(2) {} // TODO: 实现复制构造器 - DynFibonacci(DynFibonacci const &) = delete; + // 1. 参数是别人 (other/others) + // 2. 初始化列表:根据别人的进度 (other.cached) 申请一样大的新内存 + DynFibonacci(DynFibonacci const &other) : cache(new size_t[other.cached]), cached(other.cached) { + for (int i = 0; i < cached; ++i){ + cache[i]=other.cache[i]; + } + } // TODO: 实现析构器,释放缓存空间 - ~DynFibonacci(); + ~DynFibonacci(){ + delete [] cache; + } // TODO: 实现正确的缓存优化斐波那契计算 size_t get(int i) { - for (; false; ++cached) { + for (; cached<=i; ++cached) { cache[cached] = cache[cached - 1] + cache[cached - 2]; } return cache[i]; diff --git a/exercises/16_class_move/main.cpp b/exercises/16_class_move/main.cpp index 8d2c421da..1817e7c6f 100644 --- a/exercises/16_class_move/main.cpp +++ b/exercises/16_class_move/main.cpp @@ -1,4 +1,5 @@ #include "../exercise.h" +#include // READ: 左值右值(概念) // READ: 左值右值(细节) @@ -14,27 +15,36 @@ class DynFibonacci { int cached; public: - // TODO: 实现动态设置容量的构造器 - DynFibonacci(int capacity): cache(new ?), cached(?) {} + // TODO 1: 构造器 + DynFibonacci(int capacity): cache(new size_t[capacity]{0, 1}), cached(2) {} - // TODO: 实现移动构造器 - DynFibonacci(DynFibonacci &&) noexcept = delete; + // TODO 2: 移动构造器 (删掉 = delete) + DynFibonacci(DynFibonacci &&other) noexcept + : cache(std::exchange(other.cache, nullptr)), + cached(std::exchange(other.cached, 0)) {} - // TODO: 实现移动赋值 - // NOTICE: ⚠ 注意移动到自身问题 ⚠ - DynFibonacci &operator=(DynFibonacci &&) noexcept = delete; + // TODO 3: 移动赋值 (删掉 = delete) + DynFibonacci &operator=(DynFibonacci &&other) noexcept { + if (this != &other) { + delete[] cache; + cache = std::exchange(other.cache, nullptr); + cached = std::exchange(other.cached, 0); + } + return *this; + } - // TODO: 实现析构器,释放缓存空间 - ~DynFibonacci(); + // TODO 4: 析构器 + ~DynFibonacci() { + delete[] cache; + } - // TODO: 实现正确的缓存优化斐波那契计算 + // TODO 5: 修复循环 size_t operator[](int i) { - for (; false; ++cached) { + for (; cached <= i; ++cached) { // 把 false 改成 cached <= i cache[cached] = cache[cached - 1] + cache[cached - 2]; } return cache[i]; } - // NOTICE: 不要修改这个方法 size_t operator[](int i) const { ASSERT(i <= cached, "i out of range"); diff --git a/exercises/17_class_derive/main.cpp b/exercises/17_class_derive/main.cpp index 819ae72fc..0c245df4f 100644 --- a/exercises/17_class_derive/main.cpp +++ b/exercises/17_class_derive/main.cpp @@ -50,9 +50,9 @@ int main(int argc, char **argv) { B b = B(3); // TODO: 补全三个类型的大小 - static_assert(sizeof(X) == ?, "There is an int in X"); - static_assert(sizeof(A) == ?, "There is an int in A"); - static_assert(sizeof(B) == ?, "B is an A with an X"); + static_assert(sizeof(X) == 4, "There is an int in X"); + static_assert(sizeof(A) == 4, "There is an int in A"); + static_assert(sizeof(B) == 8, "B is an A with an X"); i = 0; std::cout << std::endl diff --git a/exercises/18_class_virtual/main.cpp b/exercises/18_class_virtual/main.cpp index ac6382413..344709e4c 100644 --- a/exercises/18_class_virtual/main.cpp +++ b/exercises/18_class_virtual/main.cpp @@ -42,38 +42,38 @@ int main(int argc, char **argv) { C c; D d; - ASSERT(a.virtual_name() == '?', MSG); - ASSERT(b.virtual_name() == '?', MSG); - ASSERT(c.virtual_name() == '?', MSG); - ASSERT(d.virtual_name() == '?', MSG); - ASSERT(a.direct_name() == '?', MSG); - ASSERT(b.direct_name() == '?', MSG); - ASSERT(c.direct_name() == '?', MSG); - ASSERT(d.direct_name() == '?', MSG); + ASSERT(a.virtual_name() == 'A', MSG); + ASSERT(b.virtual_name() == 'B', MSG); + ASSERT(c.virtual_name() == 'C', MSG); + ASSERT(d.virtual_name() == 'C', MSG); + ASSERT(a.direct_name() == 'A', MSG); + ASSERT(b.direct_name() == 'B', MSG); + ASSERT(c.direct_name() == 'C', MSG); + ASSERT(d.direct_name() == 'D', MSG); A &rab = b; B &rbc = c; C &rcd = d; - ASSERT(rab.virtual_name() == '?', MSG); - ASSERT(rbc.virtual_name() == '?', MSG); - ASSERT(rcd.virtual_name() == '?', MSG); - ASSERT(rab.direct_name() == '?', MSG); - ASSERT(rbc.direct_name() == '?', MSG); - ASSERT(rcd.direct_name() == '?', MSG); + ASSERT(rab.virtual_name() == 'B', MSG); + ASSERT(rbc.virtual_name() == 'C', MSG); + ASSERT(rcd.virtual_name() == 'C', MSG); + ASSERT(rab.direct_name() == 'A', MSG); + ASSERT(rbc.direct_name() == 'B', MSG); + ASSERT(rcd.direct_name() == 'C', MSG); A &rac = c; B &rbd = d; - ASSERT(rac.virtual_name() == '?', MSG); - ASSERT(rbd.virtual_name() == '?', MSG); - ASSERT(rac.direct_name() == '?', MSG); - ASSERT(rbd.direct_name() == '?', MSG); + ASSERT(rac.virtual_name() == 'C', MSG); + ASSERT(rbd.virtual_name() == 'C', MSG); + ASSERT(rac.direct_name() == 'A', MSG); + ASSERT(rbd.direct_name() == 'B', MSG); A &rad = d; - ASSERT(rad.virtual_name() == '?', MSG); - ASSERT(rad.direct_name() == '?', MSG); + ASSERT(rad.virtual_name() == 'C', MSG); + ASSERT(rad.direct_name() == 'A', MSG); return 0; } diff --git a/exercises/19_class_virtual_destruct/main.cpp b/exercises/19_class_virtual_destruct/main.cpp index cdd54f74f..229b5efd3 100644 --- a/exercises/19_class_virtual_destruct/main.cpp +++ b/exercises/19_class_virtual_destruct/main.cpp @@ -5,12 +5,12 @@ struct A { // TODO: 正确初始化静态字段 - static int num_a = 0; + static int num_a; A() { ++num_a; } - ~A() { + virtual ~A() { --num_a; } @@ -20,7 +20,7 @@ struct A { }; struct B final : public A { // TODO: 正确初始化静态字段 - static int num_b = 0; + static int num_b; B() { ++num_b; @@ -34,13 +34,16 @@ struct B final : public A { } }; +int A::num_a = 0; +int B::num_b = 0; + int main(int argc, char **argv) { auto a = new A; auto b = new B; - ASSERT(A::num_a == ?, "Fill in the correct value for A::num_a"); - ASSERT(B::num_b == ?, "Fill in the correct value for B::num_b"); - ASSERT(a->name() == '?', "Fill in the correct value for a->name()"); - ASSERT(b->name() == '?', "Fill in the correct value for b->name()"); + ASSERT(A::num_a == 2, "Fill in the correct value for A::num_a"); + ASSERT(B::num_b == 1, "Fill in the correct value for B::num_b"); + ASSERT(a->name() == 'A', "Fill in the correct value for a->name()"); + ASSERT(b->name() == 'B', "Fill in the correct value for b->name()"); delete a; delete b; @@ -48,13 +51,13 @@ int main(int argc, char **argv) { ASSERT(B::num_b == 0, "Every B was destroyed"); A *ab = new B;// 派生类指针可以随意转换为基类指针 - ASSERT(A::num_a == ?, "Fill in the correct value for A::num_a"); - ASSERT(B::num_b == ?, "Fill in the correct value for B::num_b"); - ASSERT(ab->name() == '?', "Fill in the correct value for ab->name()"); + ASSERT(A::num_a == 1, "Fill in the correct value for A::num_a"); + ASSERT(B::num_b == 1, "Fill in the correct value for B::num_b"); + ASSERT(ab->name() == 'B', "Fill in the correct value for ab->name()"); // TODO: 基类指针无法随意转换为派生类指针,补全正确的转换语句 - B &bb = *ab; - ASSERT(bb.name() == '?', "Fill in the correct value for bb->name()"); + B &bb = dynamic_cast(*ab);; + ASSERT(bb.name() == 'B', "Fill in the correct value for bb->name()"); // TODO: ---- 以下代码不要修改,通过改正类定义解决编译问题 ---- delete ab;// 通过指针可以删除指向的对象,即使是多态对象 diff --git a/exercises/20_function_template/main.cpp b/exercises/20_function_template/main.cpp index cb6d978d3..3d8a0dbaa 100644 --- a/exercises/20_function_template/main.cpp +++ b/exercises/20_function_template/main.cpp @@ -2,7 +2,9 @@ // READ: 函数模板 // TODO: 将这个函数模板化 -int plus(int a, int b) { +// template 告诉编译器:下面这个函数是个模具,T 是个占位符 +template +T plus(T a, T b) { return a + b; } @@ -14,7 +16,7 @@ int main(int argc, char **argv) { ASSERT(plus(1.25f, 2.5f) == 3.75f, "Plus two float"); ASSERT(plus(1.25, 2.5) == 3.75, "Plus two double"); // TODO: 修改判断条件使测试通过 - ASSERT(plus(0.1, 0.2) == 0.3, "How to make this pass?"); + ASSERT(std::abs(plus(0.1, 0.2) - 0.3) < 1e-9, "How to make this pass?"); return 0; } diff --git a/exercises/21_runtime_datatype/main.cpp b/exercises/21_runtime_datatype/main.cpp index 9c4bf376a..953ececd7 100644 --- a/exercises/21_runtime_datatype/main.cpp +++ b/exercises/21_runtime_datatype/main.cpp @@ -18,16 +18,27 @@ struct TaggedUnion { }; // TODO: 将这个函数模板化用于 sigmoid_dyn -float sigmoid(float x) { +template +T sigmoid(T x) { return 1 / (1 + std::exp(-x)); } TaggedUnion sigmoid_dyn(TaggedUnion x) { TaggedUnion ans{x.type}; - // TODO: 根据 type 调用 sigmoid + + // 打开盲盒看标签 + switch (x.type) { + case DataType::Float: + // 如果是 Float,就取出 f,算出结果放进 ans.f + ans.f = sigmoid(x.f); + break; + case DataType::Double: + // 如果是 Double,就取出 d,算出结果放进 ans.d + ans.d = sigmoid(x.d); + break; + } return ans; } - // ---- 不要修改以下代码 ---- int main(int argc, char **argv) { TaggedUnion xf{DataType::Float}; diff --git a/exercises/22_class_template/main.cpp b/exercises/22_class_template/main.cpp index d4985d904..6d288b3b2 100644 --- a/exercises/22_class_template/main.cpp +++ b/exercises/22_class_template/main.cpp @@ -1,5 +1,6 @@ #include "../exercise.h" #include + // READ: 类模板 template @@ -7,12 +8,19 @@ struct Tensor4D { unsigned int shape[4]; T *data; + // 构造函数:初始化形状和数据 Tensor4D(unsigned int const shape_[4], T const *data_) { unsigned int size = 1; - // TODO: 填入正确的 shape 并计算 size + // 1. 计算总大小并复制 shape + for (int i = 0; i < 4; ++i) { + shape[i] = shape_[i]; + size *= shape[i]; + } + // 2. 申请内存并拷贝数据 data = new T[size]; std::memcpy(data, data_, size * sizeof(T)); } + ~Tensor4D() { delete[] data; } @@ -21,13 +29,49 @@ struct Tensor4D { Tensor4D(Tensor4D const &) = delete; Tensor4D(Tensor4D &&) noexcept = delete; - // 这个加法需要支持“单向广播”。 - // 具体来说,`others` 可以具有与 `this` 不同的形状,形状不同的维度长度必须为 1。 - // `others` 长度为 1 但 `this` 长度不为 1 的维度将发生广播计算。 - // 例如,`this` 形状为 `[1, 2, 3, 4]`,`others` 形状为 `[1, 2, 1, 4]`, - // 则 `this` 与 `others` 相加时,3 个形状为 `[1, 2, 1, 4]` 的子张量各自与 `others` 对应项相加。 + // 单向广播加法 Tensor4D &operator+=(Tensor4D const &others) { - // TODO: 实现单向广播的加法 + // 1. 预先计算哪些维度需要广播(即 others 的对应维度为 1,但 this 不是 1) + bool broadcast[4]; + for (int i = 0; i < 4; ++i) { + // 如果形状不同,意味着 others 必须广播(题目保证 others 维度如果不匹配则必为 1) + broadcast[i] = (shape[i] != others.shape[i]); + } + + auto dst = this->data; // 写入位置 + auto src = others.data; // 读取位置 + + // 标记数组 (marks):用于记录每一层循环开始时 src 的指针位置 + // 这样当需要广播(回退)时,就能找到回退的点 + T *marks[4] = {src, nullptr, nullptr, nullptr}; + + // 2. 四层循环遍历大张量 (this) + for (unsigned int i0 = 0; i0 < shape[0]; ++i0) { + // 如果第 0 维广播,指针回到本层起点 + if (broadcast[0]) src = marks[0]; + marks[1] = src; // 记录下一层的起点 + + for (unsigned int i1 = 0; i1 < shape[1]; ++i1) { + if (broadcast[1]) src = marks[1]; + marks[2] = src; + + for (unsigned int i2 = 0; i2 < shape[2]; ++i2) { + if (broadcast[2]) src = marks[2]; + marks[3] = src; + + for (unsigned int i3 = 0; i3 < shape[3]; ++i3) { + if (broadcast[3]) src = marks[3]; + + // 核心计算:对应位置相加 + *dst += *src; + + // 移动指针 + dst++; + src++; + } + } + } + } return *this; } }; @@ -46,8 +90,8 @@ int main(int argc, char **argv) { 17, 18, 19, 20, 21, 22, 23, 24}; // clang-format on - auto t0 = Tensor4D(shape, data); - auto t1 = Tensor4D(shape, data); + auto t0 = Tensor4D(shape, data); + auto t1 = Tensor4D(shape, data); t0 += t1; for (auto i = 0u; i < sizeof(data) / sizeof(*data); ++i) { ASSERT(t0.data[i] == data[i] * 2, "Tensor doubled by plus its self."); @@ -77,8 +121,8 @@ int main(int argc, char **argv) { 1}; // clang-format on - auto t0 = Tensor4D(s0, d0); - auto t1 = Tensor4D(s1, d1); + auto t0 = Tensor4D(s0, d0); + auto t1 = Tensor4D(s1, d1); t0 += t1; for (auto i = 0u; i < sizeof(d0) / sizeof(*d0); ++i) { ASSERT(t0.data[i] == 7.f, "Every element of t0 should be 7 after adding t1 to it."); @@ -99,11 +143,11 @@ int main(int argc, char **argv) { unsigned int s1[]{1, 1, 1, 1}; double d1[]{1}; - auto t0 = Tensor4D(s0, d0); - auto t1 = Tensor4D(s1, d1); + auto t0 = Tensor4D(s0, d0); + auto t1 = Tensor4D(s1, d1); t0 += t1; for (auto i = 0u; i < sizeof(d0) / sizeof(*d0); ++i) { ASSERT(t0.data[i] == d0[i] + 1, "Every element of t0 should be incremented by 1 after adding t1 to it."); } } -} +} \ No newline at end of file diff --git a/exercises/23_template_const/main.cpp b/exercises/23_template_const/main.cpp index e0105e168..6b1037da6 100644 --- a/exercises/23_template_const/main.cpp +++ b/exercises/23_template_const/main.cpp @@ -8,12 +8,15 @@ struct Tensor { unsigned int shape[N]; T *data; - Tensor(unsigned int const shape_[N]) { - unsigned int size = 1; - // TODO: 填入正确的 shape 并计算 size - data = new T[size]; - std::memset(data, 0, size * sizeof(T)); + Tensor(unsigned int const shape_[N]) { + unsigned int size = 1; + for (auto i = 0u; i < N; ++i) { + shape[i] = shape_[i]; + size *= shape[i]; } + data = new T[size]; + std::memset(data, 0, size * sizeof(T)); +} ~Tensor() { delete[] data; } @@ -31,13 +34,14 @@ struct Tensor { private: unsigned int data_index(unsigned int const indices[N]) const { - unsigned int index = 0; - for (unsigned int i = 0; i < N; ++i) { - ASSERT(indices[i] < shape[i], "Invalid index"); - // TODO: 计算 index - } - return index; + unsigned int index = 0, mul = 1; + for (auto i = N - 1; i < N; --i) { + ASSERT(indices[i] < shape[i], "Invalid index"); + index += mul * indices[i]; + mul *= shape[i]; } + return index; +} }; // ---- 不要修改以下代码 ---- diff --git a/exercises/24_std_array/main.cpp b/exercises/24_std_array/main.cpp index c29718d9d..1c99d7f5e 100644 --- a/exercises/24_std_array/main.cpp +++ b/exercises/24_std_array/main.cpp @@ -8,21 +8,21 @@ int main(int argc, char **argv) { { std::array arr{{1, 2, 3, 4, 5}}; - ASSERT(arr.size() == ?, "Fill in the correct value."); - ASSERT(sizeof(arr) == ?, "Fill in the correct value."); + ASSERT(arr.size() == 5, "Fill in the correct value."); + ASSERT(sizeof(arr) == 20, "Fill in the correct value."); int ans[]{1, 2, 3, 4, 5}; - ASSERT(std::memcmp(arr.?, ans, ?) == 0, "Fill in the correct values."); + ASSERT(std::memcmp(arr.data(), ans, 20) == 0, "Fill in the correct values."); } { std::array arr; - ASSERT(arr.size() == ?, "Fill in the correct value."); - ASSERT(sizeof(arr) == ?, "Fill in the correct value."); + ASSERT(arr.size() == 8, "Fill in the correct value."); + ASSERT(sizeof(arr) == 64, "Fill in the correct value."); } { std::array arr{"Hello, InfiniTensor!"}; - ASSERT(arr.size() == ?, "Fill in the correct value."); - ASSERT(sizeof(arr) == ?, "Fill in the correct value."); - ASSERT(std::strcmp(arr.?, "Hello, InfiniTensor!") == 0, "Fill in the correct value."); + ASSERT(arr.size() == 21, "Fill in the correct value."); + ASSERT(sizeof(arr) == 21, "Fill in the correct value."); + ASSERT(std::strcmp(arr.data(), "Hello, InfiniTensor!") == 0, "Fill in the correct value."); } return 0; } diff --git a/exercises/25_std_vector/main.cpp b/exercises/25_std_vector/main.cpp index f9e41bb78..679fb4a58 100644 --- a/exercises/25_std_vector/main.cpp +++ b/exercises/25_std_vector/main.cpp @@ -4,87 +4,91 @@ // READ: std::vector -// TODO: 将下列 `?` 替换为正确的代码 int main(int argc, char **argv) { { std::vector vec{1, 2, 3, 4, 5}; - ASSERT(vec.size() == ?, "Fill in the correct value."); - // THINK: `std::vector` 的大小是什么意思?与什么有关? - ASSERT(sizeof(vec) == ?, "Fill in the correct value."); + ASSERT(vec.size() == 5, "Fill in the correct value."); + // vector 本身大小固定为 24 字节(3 个指针) + ASSERT(sizeof(vec) == 24, "Fill in the correct value."); int ans[]{1, 2, 3, 4, 5}; - ASSERT(std::memcmp(vec.?, ans, sizeof(ans)) == 0, "Fill in the correct values."); + ASSERT(std::memcmp(vec.data(), ans, sizeof(ans)) == 0, "Fill in the correct values."); } { std::vector vec{1, 2, 3, 4, 5}; { - ASSERT(vec.size() == ?, "Fill in the correct value."); - ASSERT(sizeof(vec) == ?, "Fill in the correct value."); + ASSERT(vec.size() == 5, "Fill in the correct value."); + ASSERT(sizeof(vec) == 24, "Fill in the correct value."); double ans[]{1, 2, 3, 4, 5}; - ASSERT(std::memcmp(vec.?, ans, sizeof(ans)) == 0, "Fill in the correct values."); + ASSERT(std::memcmp(vec.data(), ans, sizeof(ans)) == 0, "Fill in the correct values."); } { vec.push_back(6); - ASSERT(vec.size() == ?, "Fill in the correct value."); - ASSERT(sizeof(vec) == ?, "Fill in the correct value."); + ASSERT(vec.size() == 6, "Fill in the correct value."); + ASSERT(sizeof(vec) == 24, "Fill in the correct value."); vec.pop_back(); - ASSERT(vec.size() == ?, "Fill in the correct value."); - ASSERT(sizeof(vec) == ?, "Fill in the correct value."); + ASSERT(vec.size() == 5, "Fill in the correct value."); + ASSERT(sizeof(vec) == 24, "Fill in the correct value."); } { vec[4] = 6; - ASSERT(vec[0] == ?, "Fill in the correct value."); - ASSERT(vec[1] == ?, "Fill in the correct value."); - ASSERT(vec[2] == ?, "Fill in the correct value."); - ASSERT(vec[3] == ?, "Fill in the correct value."); - ASSERT(vec[4] == ?, "Fill in the correct value."); + ASSERT(vec[0] == 1, "Fill in the correct value."); + ASSERT(vec[1] == 2, "Fill in the correct value."); + ASSERT(vec[2] == 3, "Fill in the correct value."); + ASSERT(vec[3] == 4, "Fill in the correct value."); + ASSERT(vec[4] == 6, "Fill in the correct value."); } { - // THINK: `std::vector` 插入删除的时间复杂度是什么? - vec.insert(?, 1.5); + // 在 begin()+1 的位置插入 1.5 -> {1, 1.5, 2, 3, 4, 6} + vec.insert(vec.begin() + 1, 1.5); ASSERT((vec == std::vector{1, 1.5, 2, 3, 4, 6}), "Make this assertion pass."); - vec.erase(?); + // 删掉 begin()+3 的位置 (即数字 3) -> {1, 1.5, 2, 4, 6} + vec.erase(vec.begin() + 3); ASSERT((vec == std::vector{1, 1.5, 2, 4, 6}), "Make this assertion pass."); } { + // 缩容:让 capacity 变得和 size 一样大 vec.shrink_to_fit(); - ASSERT(vec.capacity() == ?, "Fill in the correct value."); + ASSERT(vec.capacity() == 5, "Fill in the correct value."); + // 清空:size 变 0,但 capacity 不一定变(通常不变) vec.clear(); ASSERT(vec.empty(), "`vec` is empty now."); - ASSERT(vec.size() == ?, "Fill in the correct value."); - ASSERT(vec.capacity() == ?, "Fill in the correct value."); + ASSERT(vec.size() == 0, "Fill in the correct value."); + ASSERT(vec.capacity() == 5, "Fill in the correct value."); } } { - std::vector vec(?, ?); // TODO: 调用正确的构造函数 + // 构造函数:48 个 'z' + std::vector vec(48, 'z'); ASSERT(vec[0] == 'z', "Make this assertion pass."); ASSERT(vec[47] == 'z', "Make this assertion pass."); ASSERT(vec.size() == 48, "Make this assertion pass."); - ASSERT(sizeof(vec) == ?, "Fill in the correct value."); + ASSERT(sizeof(vec) == 24, "Fill in the correct value."); { auto capacity = vec.capacity(); - vec.resize(16); - ASSERT(vec.size() == ?, "Fill in the correct value."); - ASSERT(vec.capacity() == ?, "Fill in a correct identifier."); + vec.resize(16); // 只要前 16 个 + ASSERT(vec.size() == 16, "Fill in the correct value."); + // resize 变小通常不改变 capacity + ASSERT(vec.capacity() == capacity, "Fill in a correct identifier."); } { - vec.reserve(256); - ASSERT(vec.size() == ?, "Fill in the correct value."); - ASSERT(vec.capacity() == ?, "Fill in the correct value."); + vec.reserve(256); // 预订 256 个位子 + ASSERT(vec.size() == 16, "Fill in the correct value."); + ASSERT(vec.capacity() == 256, "Fill in the correct value."); } { vec.push_back('a'); vec.push_back('b'); vec.push_back('c'); vec.push_back('d'); - ASSERT(vec.size() == ?, "Fill in the correct value."); - ASSERT(vec.capacity() == ?, "Fill in the correct value."); - ASSERT(vec[15] == ?, "Fill in the correct value."); - ASSERT(vec[?] == 'a', "Fill in the correct value."); - ASSERT(vec[?] == 'b', "Fill in the correct value."); - ASSERT(vec[?] == 'c', "Fill in the correct value."); - ASSERT(vec[?] == 'd', "Fill in the correct value."); + ASSERT(vec.size() == 20, "Fill in the correct value."); // 16 + 4 = 20 + ASSERT(vec.capacity() == 256, "Fill in the correct value."); + ASSERT(vec[15] == 'z', "Fill in the correct value."); + ASSERT(vec[16] == 'a', "Fill in the correct value."); + ASSERT(vec[17] == 'b', "Fill in the correct value."); + ASSERT(vec[18] == 'c', "Fill in the correct value."); + ASSERT(vec[19] == 'd', "Fill in the correct value."); } } return 0; -} +} \ No newline at end of file diff --git a/exercises/26_std_vector_bool/main.cpp b/exercises/26_std_vector_bool/main.cpp index b4ab4f9c4..1b06f4666 100644 --- a/exercises/26_std_vector_bool/main.cpp +++ b/exercises/26_std_vector_bool/main.cpp @@ -4,31 +4,43 @@ // READ: std::vector // READ: 模板特化 -// TODO: 将下列 `?` 替换为正确的代码 int main(int argc, char **argv) { - std::vector vec(?, ?);// TODO: 正确调用构造函数 + // 1. 构造 100 个 true + std::vector vec(100, true); ASSERT(vec[0], "Make this assertion pass."); ASSERT(vec[99], "Make this assertion pass."); ASSERT(vec.size() == 100, "Make this assertion pass."); - // NOTICE: 平台相关!注意 CI:Ubuntu 上的值。 + + // NOTICE: 平台相关!在 Linux/GCC 64位环境下,vector 通常是 40 字节 + // 因为它需要额外存储位偏移量 (Bit Offset) std::cout << "sizeof(std::vector) = " << sizeof(std::vector) << std::endl; - ASSERT(sizeof(vec) == ?, "Fill in the correct value."); + ASSERT(sizeof(vec) == 40, "Fill in the correct value."); + { vec[20] = false; - ASSERT(?vec[20], "Fill in `vec[20]` or `!vec[20]`."); + // 既然设为 false 了,断言就要取反 (!) + ASSERT(!vec[20], "Fill in `vec[20]` or `!vec[20]`."); } { vec.push_back(false); - ASSERT(vec.size() == ?, "Fill in the correct value."); - ASSERT(?vec[100], "Fill in `vec[100]` or `!vec[100]`."); + // 大小变成 101 + ASSERT(vec.size() == 101, "Fill in the correct value."); + // 新加入的是 false + ASSERT(!vec[100], "Fill in `vec[100]` or `!vec[100]`."); } { + // 重点:std::vector 的 operator[] 返回的不是 bool&, + // 而是一个代理对象 (std::vector::reference)。 + // 它像一个“遥控器”,当你修改它时,它会去修改 vector 内部那个具体的 bit。 auto ref = vec[30]; - ASSERT(?ref, "Fill in `ref` or `!ref`"); - ref = false; - ASSERT(?ref, "Fill in `ref` or `!ref`"); + ASSERT(ref, "Fill in `ref` or `!ref`"); // 此时还是 true + + ref = false; // 按下遥控器,修改内部数据 + ASSERT(!ref, "Fill in `ref` or `!ref`"); // 遥控器显示 false + // THINK: WHAT and WHY? - ASSERT(?vec[30], "Fill in `vec[30]` or `!vec[30]`."); + // 因为 ref 是代理引用,所以原数组也被修改了! + ASSERT(!vec[30], "Fill in `vec[30]` or `!vec[30]`."); } return 0; -} +} \ No newline at end of file diff --git a/exercises/27_strides/main.cpp b/exercises/27_strides/main.cpp index baceaf2a9..466a1dce9 100644 --- a/exercises/27_strides/main.cpp +++ b/exercises/27_strides/main.cpp @@ -15,9 +15,13 @@ using udim = unsigned int; /// @return 张量每维度的访问步长 std::vector strides(std::vector const &shape) { std::vector strides(shape.size()); - // TODO: 完成函数体,根据张量形状计算张量连续存储时的步长。 - // READ: 逆向迭代器 std::vector::rbegin - // 使用逆向迭代器可能可以简化代码 + auto ans = strides.rbegin(); + *ans = 1; + for (auto it = shape.rbegin(); + it + 1 != shape.rend(); + ++it, ++ans) { + ans[1] = ans[0] * *it; + } return strides; } diff --git a/exercises/28_std_string/main.cpp b/exercises/28_std_string/main.cpp index d8b276274..3b5718491 100644 --- a/exercises/28_std_string/main.cpp +++ b/exercises/28_std_string/main.cpp @@ -4,15 +4,20 @@ // READ: 字符串 int main(int argc, char **argv) { - // READ: 字符串字面量 + // 开启 "..."s 后缀功能 using namespace std::string_literals; - auto hello = "Hello"s; - auto world = "world"; - // READ: `decltype` 表达式 - // READ: `std::is_same_v` 元编程判别 - ASSERT((std::is_same_v), "Fill in the missing type."); - ASSERT((std::is_same_v), "Fill in the missing type."); - // TODO: 将 `?` 替换为正确的字符串 - ASSERT(hello + ", " + world + '!' == "?", "Fill in the missing string."); + + auto hello = "Hello"s; // 类型是 std::string + auto world = "world"; // 类型是 const char * + + + ASSERT((std::is_same_v), "Fill in the missing type."); + + + ASSERT((std::is_same_v), "Fill in the missing type."); + + + ASSERT(hello + ", " + world + '!' == "Hello, world!", "Fill in the missing string."); + return 0; -} +} \ No newline at end of file diff --git a/exercises/29_std_map/main.cpp b/exercises/29_std_map/main.cpp index fcccca347..842fc560c 100644 --- a/exercises/29_std_map/main.cpp +++ b/exercises/29_std_map/main.cpp @@ -4,14 +4,28 @@ // READ: `std::map` // READ: `std::unordered_map` +#include "../exercise.h" +#include + +// READ: `std::map` +// READ: `std::unordered_map` + template bool key_exists(std::map const &map, k const &key) { - // TODO: 实现函数 + // 方法 1:经典迭代器法 (C++98 ~ C++17) + // find 如果找不到,会返回 map.end() + return map.find(key) != map.end(); + + // 方法 2:C++20 新特性 (如果你的编译器够新) + // return map.contains(key); } template void set(std::map &map, k key, v value) { - // TODO: 实现函数 + // map 的 [] 运算符非常强大: + // 1. 如果 key 存在,它就返回对应的 value 的引用(让你覆盖)。 + // 2. 如果 key 不存在,它会自动创建一个新的,并返回引用(让你赋值)。 + map[key] = value; } // ---- 不要修改以下代码 ---- diff --git a/exercises/30_std_unique_ptr/main.cpp b/exercises/30_std_unique_ptr/main.cpp index 9b98b5794..b2d1a2834 100644 --- a/exercises/30_std_unique_ptr/main.cpp +++ b/exercises/30_std_unique_ptr/main.cpp @@ -3,24 +3,18 @@ #include #include #include - // READ: `std::unique_ptr` - std::vector RECORDS; - class Resource { std::string _records; - public: void record(char record) { _records.push_back(record); } - ~Resource() { RECORDS.push_back(_records); } }; - using Unique = std::unique_ptr; Unique reset(Unique ptr) { if (ptr) ptr->record('r'); @@ -34,37 +28,29 @@ Unique forward(Unique ptr) { if (ptr) ptr->record('f'); return ptr; } - int main(int argc, char **argv) { std::vector problems[3]; - drop(forward(reset(nullptr))); problems[0] = std::move(RECORDS); - forward(drop(reset(forward(forward(reset(nullptr)))))); problems[1] = std::move(RECORDS); - drop(drop(reset(drop(reset(reset(nullptr)))))); problems[2] = std::move(RECORDS); - // ---- 不要修改以上代码 ---- - std::vector answers[]{ {"fd"}, // TODO: 分析 problems[1] 中资源的生命周期,将记录填入 `std::vector` // NOTICE: 此题结果依赖对象析构逻辑,平台相关,提交时以 CI 实际运行平台为准 - {"", "", "", "", "", "", "", ""}, - {"", "", "", "", "", "", "", ""}, + {"d", "ffr"}, + {"d", "d","r"}, }; // ---- 不要修改以下代码 ---- - for (auto i = 0; i < 3; ++i) { ASSERT(problems[i].size() == answers[i].size(), "wrong size"); for (auto j = 0; j < problems[i].size(); ++j) { ASSERT(std::strcmp(problems[i][j].c_str(), answers[i][j]) == 0, "wrong location"); } } - return 0; -} +} \ No newline at end of file diff --git a/exercises/31_std_shared_ptr/main.cpp b/exercises/31_std_shared_ptr/main.cpp index febbbcc6f..1db4ff82c 100644 --- a/exercises/31_std_shared_ptr/main.cpp +++ b/exercises/31_std_shared_ptr/main.cpp @@ -1,45 +1,44 @@ #include "../exercise.h" -#include +#include // 别忘了这个头文件 -// READ: `std::shared_ptr` -// READ: `std::weak_ptr` - -// TODO: 将下列 `?` 替换为正确的值 int main(int argc, char **argv) { auto shared = std::make_shared(10); std::shared_ptr ptrs[]{shared, shared, shared}; std::weak_ptr observer = shared; - ASSERT(observer.use_count() == ?, ""); + ASSERT(observer.use_count() == 4, ""); ptrs[0].reset(); - ASSERT(observer.use_count() == ?, ""); + ASSERT(observer.use_count() == 3, ""); ptrs[1] = nullptr; - ASSERT(observer.use_count() == ?, ""); + ASSERT(observer.use_count() == 2, ""); ptrs[2] = std::make_shared(*shared); - ASSERT(observer.use_count() == ?, ""); + ASSERT(observer.use_count() == 1, ""); ptrs[0] = shared; ptrs[1] = shared; ptrs[2] = std::move(shared); - ASSERT(observer.use_count() == ?, ""); + ASSERT(observer.use_count() == 3, ""); - std::ignore = std::move(ptrs[0]); + std::ignore = std::move(ptrs[0]); + ptrs[1] = std::move(ptrs[1]); + ptrs[1] = std::move(ptrs[2]); - ASSERT(observer.use_count() == ?, ""); + ASSERT(observer.use_count() == 2, ""); shared = observer.lock(); - ASSERT(observer.use_count() == ?, ""); + + ASSERT(observer.use_count() == 3, ""); shared = nullptr; for (auto &ptr : ptrs) ptr = nullptr; - ASSERT(observer.use_count() == ?, ""); + ASSERT(observer.use_count() == 0, ""); shared = observer.lock(); - ASSERT(observer.use_count() == ?, ""); + ASSERT(observer.use_count() == 0, ""); return 0; -} +} \ No newline at end of file diff --git a/exercises/32_std_transform/main.cpp b/exercises/32_std_transform/main.cpp index f4dc25a5c..bb8c53eda 100644 --- a/exercises/32_std_transform/main.cpp +++ b/exercises/32_std_transform/main.cpp @@ -9,6 +9,11 @@ int main(int argc, char **argv) { std::vector val{8, 13, 21, 34, 55}; // TODO: 调用 `std::transform`,将 `v` 中的每个元素乘以 2,并转换为字符串,存入 `ans` + std::vector ans(val.size()); + + std::transform(val.begin(), val.end(), ans.begin(), [](int n) { + return std::to_string(n * 2); + }); // std::vector ans ASSERT(ans.size() == val.size(), "ans size should be equal to val size"); ASSERT(ans[0] == "16", "ans[0] should be 16"); diff --git a/exercises/33_std_accumulate/main.cpp b/exercises/33_std_accumulate/main.cpp index 6326929d5..06147d893 100644 --- a/exercises/33_std_accumulate/main.cpp +++ b/exercises/33_std_accumulate/main.cpp @@ -12,6 +12,11 @@ int main(int argc, char **argv) { // - 连续存储; // 的张量占用的字节数 // int size = + // 初始值设为 sizeof(DataType) (也就是 4),然后依次乘上 shape 里的每一个数 + // lambda 表达式 [](int a, int b) { return a * b; } 定义了乘法操作 + int size = std::accumulate(shape, shape + 4, sizeof(DataType), [](int a, int b) { + return a * b; + }); ASSERT(size == 602112, "4x1x3x224x224 = 602112"); return 0; }