Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions exercises/exercises/00_hello_world/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "../exercise.h"

// READ: std streams <https://zh.cppreference.com/w/cpp/io/c/std_streams>
// READ: 流修饰符 <https://zh.cppreference.com/w/cpp/io/manip>
// READ: format in cxx20 <https://zh.cppreference.com/w/cpp/utility/format/format>

int main(int argc, char **argv) {
// TODO: 在控制台输出 "Hello, InfiniTensor!" 并换行
std::cout << "Hello, InfiniTensor!" <<std::endl;
return 0;
}
11 changes: 11 additions & 0 deletions exercises/exercises/01_variable&add/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "../exercise.h"

// READ: 运算符 <https://zh.cppreference.com/w/cpp/language/expressions#.E8.BF.90.E7.AE.97.E7.AC.A6>

int main(int argc, char **argv) {
// TODO: 补全变量定义并打印加法运算
// x ?
int x=5;
std::cout << x << " + " << x << " = " << x + x << std::endl;
return 0;
}
20 changes: 20 additions & 0 deletions exercises/exercises/02_function/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "../exercise.h"

// READ: 声明 <https://zh.cppreference.com/w/cpp/language/declarations>
// NOTICE: cppreference 中的示例中指出了复杂声明的解读法,建议认真阅读。
// NOTICE: 补充由内而外读法的机翻解释 <https://learn.microsoft.com/zh-cn/cpp/c-language/interpreting-more-complex-declarators?view=msvc-170>

// TODO: 在这里声明函数
int add(int x,int y);
int main(int argc, char **argv) {
ASSERT(add(123, 456) == 123 + 456, "add(123, 456) should be 123 + 456");

auto x = 1, y = 2;
std::cout << x << " + " << y << " = " << add(x, y) << std::endl;
return 0;
}

int add(int a, int b) {
// TODO: 补全函数定义,但不要移动代码行
return a+b;
}
26 changes: 26 additions & 0 deletions exercises/exercises/03_argument&parameter/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include "../exercise.h"

// READ: <https://stackoverflow.com/questions/156767/whats-the-difference-between-an-argument-and-a-parameter>
// THINK: 参数都有哪些传递方式?如何选择传递方式?

void func(int);

// TODO: 为下列 ASSERT 填写正确的值
int main(int argc, char **argv) {
auto arg = 99;
ASSERT(arg == 99, "arg should be ?");
std::cout << "befor func call: " << arg << std::endl;
func(arg);
ASSERT(arg == 99, "arg should be ?");
std::cout << "after func call: " << arg << std::endl;
return 0;
}

// TODO: 为下列 ASSERT 填写正确的值
void func(int param) {
ASSERT(param == 99, "param should be ?");
std::cout << "befor add: " << param << std::endl;
param += 1;
ASSERT(param == 100, "param should be ?");
std::cout << "after add: " << param << std::endl;
}
19 changes: 19 additions & 0 deletions exercises/exercises/04_static/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include "../exercise.h"

// READ: `static` 关键字 <https://zh.cppreference.com/w/cpp/language/storage_duration>
// THINK: 这个函数的两个 `static` 各自的作用是什么?
static int func(int param) {
static int static_ = param;
// std::cout << "static_ = " << static_ << std::endl;
return static_++;
}

int main(int argc, char **argv) {
// TODO: 将下列 `?` 替换为正确的数字
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;
}
26 changes: 26 additions & 0 deletions exercises/exercises/05_constexpr/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#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);
}
}

int main(int argc, char **argv) {
constexpr 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 = 10;
constexpr auto ANS = fibonacci(ANS_N);
std::cout << "fibonacci(" << ANS_N << ") = " << ANS << std::endl;

return 0;
}
26 changes: 26 additions & 0 deletions exercises/exercises/06_array/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include "../exercise.h"

// READ: 数组 <https://zh.cppreference.com/w/cpp/language/array>

unsigned long long arr[90]{0, 1};
unsigned long long fibonacci(int i) {
switch (i) {
case 0:
return 0;
case 1:
return 1;
default:
// TODO: 补全三目表达式缺失的部分
return arr[i] ? arr[i] : (arr[i] = fibonacci(i - 1) + fibonacci(i - 2));
}
}

int main(int argc, char **argv) {
// TODO: 为此 ASSERT 填写正确的值
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");
ASSERT(fibonacci(80) == 23416728348467685, "fibonacci(80) should be 23416728348467685");
return 0;
}
28 changes: 28 additions & 0 deletions exercises/exercises/07_loop/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "../exercise.h"

// TODO: 改正函数实现,实现正确的缓存优化斐波那契计算
// THINk: 这个函数是一个纯函数(pure function)吗?
// READ: 纯函数 <https://zh.wikipedia.org/wiki/%E7%BA%AF%E5%87%BD%E6%95%B0>
static unsigned long long fibonacci(int i) {
// TODO: 为缓存设置正确的初始值
static unsigned long long cache[96]{0,1}, cached=2;
// TODO: 设置正确的循环条件
for (; cached<=i; ++cached) {
cache[cached] = cache[cached - 1] + cache[cached - 2];
}
return cache[i];
}

// ---- 不要修改以下代码 ----
int main(int argc, char **argv) {
ASSERT(fibonacci(0) == 0, "fibonacci(0) should be 0");
ASSERT(fibonacci(1) == 1, "fibonacci(1) should be 1");
ASSERT(fibonacci(2) == 1, "fibonacci(2) should be 1");
ASSERT(fibonacci(3) == 2, "fibonacci(3) should be 2");
ASSERT(fibonacci(10) == 55, "fibonacci(10) should be 55");

auto fib90 = fibonacci(90);
std::cout << "fibonacci(90) = " << fib90 << std::endl;
ASSERT(fib90 == 2880067194370816120, "fibonacci(90) should be 2880067194370816120");
return 0;
}
35 changes: 35 additions & 0 deletions exercises/exercises/08_pointer/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "../exercise.h"

// READ: 数组向指针退化 <https://zh.cppreference.com/w/cpp/language/array#%E6%95%B0%E7%BB%84%E5%88%B0%E6%8C%87%E9%92%88%E7%9A%84%E9%80%80%E5%8C%96>
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=2;i<len;i++){
int *pre1=ptr+((i-1)*stride);
int *pre2=ptr+((i-2)*stride);
int *cur=ptr+((i)*stride);
if(*cur!=*pre1+*pre2)return false;
}
return true;
}

// ---- 不要修改以下代码 ----
int main(int argc, char **argv) {
int arr0[]{0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55},
arr1[]{0, 1, 2, 3, 4, 5, 6},
arr2[]{99, 98, 4, 1, 7, 2, 11, 3, 18, 5, 29, 8, 47, 13, 76, 21, 123, 34, 199, 55, 322, 0, 0};
// clang-format off
ASSERT( is_fibonacci(arr0 , sizeof(arr0) / sizeof(*arr0) , 1), "arr0 is Fibonacci" );
ASSERT( is_fibonacci(arr0 + 2, sizeof(arr0) / sizeof(*arr0) - 4, 1), "part of arr0 is Fibonacci" );
ASSERT(!is_fibonacci(arr1 , sizeof(arr1) / sizeof(*arr1) , 1), "arr1 is not Fibonacci");
ASSERT( is_fibonacci(arr1 + 1, 3 , 1), "part of arr1 is Fibonacci" );
ASSERT(!is_fibonacci(arr2 , sizeof(arr2) / sizeof(*arr2) , 1), "arr2 is not Fibonacci");
ASSERT( is_fibonacci(arr2 + 2, 10 , 2), "part of arr2 is Fibonacci" );
ASSERT( is_fibonacci(arr2 + 3, 9 , 2), "part of arr2 is Fibonacci" );
ASSERT(!is_fibonacci(arr2 + 3, 10 , 2), "guard check" );
ASSERT(!is_fibonacci(arr2 + 1, 10 , 2), "guard check" );
// clang-format on
return 0;
}
50 changes: 50 additions & 0 deletions exercises/exercises/09_enum&union/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include "../exercise.h"

// READ: 枚举类型 <https://zh.cppreference.com/w/cpp/language/enum>

// `enum` 是 C 的兼容类型,本质上其对应类型的常量。
// 在 `enum` 中定义标识符等价于定义 constexpr 常量,
// 这些标识符不需要前缀,可以直接引用。
// 因此 `enum` 定义会污染命名空间。
enum ColorEnum : unsigned char {
COLOR_RED = 31,
COLOR_GREEN,
COLOR_YELLOW,
COLOR_BLUE,
};

// 有作用域枚举型是 C++ 引入的类型安全枚举。
// 其内部标识符需要带前缀引用,如 `Color::Red`。
// 作用域枚举型可以避免命名空间污染,并提供类型安全保证。
enum class Color : int {
Red = COLOR_RED,
Green,
Yellow,
Blue,
};

ColorEnum convert_by_pun(Color c) {
// READ: <https://zh.cppreference.com/w/cpp/language/union>
// `union` 表示在同一内存位置存储的不同类型的值。
// 其常见用法是实现类型双关转换,即将一种类型的值转换为另一种无关类型的值。
// 但这种写法实际上仅在 C 语言良定义,在 C++ 中是未定义行为。
// 这是比较少见的 C++ 不与 C 保持兼容的特性。
// READ: 类型双关 <https://tttapa.github.io/Pages/Programming/Cpp/Practices/type-punning.html>
union TypePun {
ColorEnum e;
Color c;
};

TypePun pun;
// TODO: 补全类型双关转换
pun.c=c;
return pun.e;
}

int main(int argc, char **argv) {
ASSERT(convert_by_pun(Color::Red) == COLOR_RED, "Type punning conversion");
ASSERT(convert_by_pun(Color::Green) == COLOR_GREEN, "Type punning conversion");
ASSERT(convert_by_pun(Color::Yellow) == COLOR_YELLOW, "Type punning conversion");
ASSERT(convert_by_pun(Color::Blue) == COLOR_BLUE, "Type punning conversion");
return 0;
}
26 changes: 26 additions & 0 deletions exercises/exercises/10_trivial/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include "../exercise.h"

// READ: Trivial type <https://learn.microsoft.com/zh-cn/cpp/cpp/trivial-standard-layout-and-pod-types?view=msvc-170>

struct FibonacciCache {
unsigned long long cache[16];
int cached;
};

// TODO: 实现正确的缓存优化斐波那契计算
static unsigned long long fibonacci(FibonacciCache &cache, int i) {
for (;cache.cached<=i ; ++cache.cached) {
cache.cache[cache.cached] = cache.cache[cache.cached - 1] + cache.cache[cache.cached - 2];
}
return cache.cache[i];
}

int main(int argc, char **argv) {
// TODO: 初始化缓存结构体,使计算正确
// NOTICE: C/C++ 中,读取未初始化的变量(包括结构体变量)是未定义行为
// READ: 初始化的各种写法 <https://zh.cppreference.com/w/cpp/language/initialization>
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;
}
22 changes: 22 additions & 0 deletions exercises/exercises/11_method/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include "../exercise.h"

struct Fibonacci {
unsigned long long cache[128];
int cached;

// TODO: 实现正确的缓存优化斐波那契计算
unsigned long long get(int i) {
for (; cached<=i; ++cached) {
cache[cached] = cache[cached - 1] + cache[cached - 2];
}
return cache[i];
}
};

int main(int argc, char **argv) {
// TODO: 初始化缓存结构体,使计算正确
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;
}
18 changes: 18 additions & 0 deletions exercises/exercises/12_method_const/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include "../exercise.h"

// READ: 有 cv 限定符的成员函数 <https://zh.cppreference.com/w/cpp/language/member_functions>

struct Fibonacci {
int numbers[11];
// TODO: 修改方法签名和实现,使测试通过
constexpr int get(int i) const {
return numbers[i];
}
};

int main(int argc, char **argv) {
Fibonacci constexpr FIB{{0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55}};
ASSERT(FIB.get(10) == 55, "fibonacci(10) should be 55");
std::cout << "fibonacci(10) = " << FIB.get(10) << std::endl;
return 0;
}
39 changes: 39 additions & 0 deletions exercises/exercises/13_class/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "../exercise.h"

// C++ 中,`class` 和 `struct` 之间的**唯一区别**是
// `class` 默认访问控制符是 `private`,
// `struct` 默认访问控制符是 `public`。
// READ: 访问说明符 <https://zh.cppreference.com/w/cpp/language/access>

// 这个 class 中的字段被 private 修饰,只能在 class 内部访问。
// 因此必须提供构造器来初始化字段。
// READ: 构造器 <https://zh.cppreference.com/w/cpp/language/constructor>
class Fibonacci {
size_t cache[16];
int cached;

public:
// TODO: 实现构造器
Fibonacci(){
cache[0]=0;
cache[1]=1;
cached=2;
}

// TODO: 实现正确的缓存优化斐波那契计算
size_t get(int i) {
for (; cached<=i; ++cached) {
cache[cached] = cache[cached - 1] + cache[cached - 2];
}
return cache[i];
}
};

int main(int argc, char **argv) {
// 现在类型拥有无参构造器,声明时会直接调用。
// 这个写法不再是未定义行为了。
Fibonacci fib;
ASSERT(fib.get(10) == 55, "fibonacci(10) should be 55");
std::cout << "fibonacci(10) = " << fib.get(10) << std::endl;
return 0;
}
Loading