# 实验目的要求 1. 使用 `C++` 语言编写简单的计算机程序,掌握 `C++` 程序从编辑、编译到运行的全过程,初步了解 `C++` 程序的特点。 2. 掌握 `C++` 语言的数据类型(包括对各种数据类型变量的定义、初始化、赋值等)、运算符和表达式的使用。 3. 掌握数据的输入输出方法。 4. 理解基本的解题技巧,掌握用自顶向下、逐步求精的过程设计算法。 5. 熟练掌握 `if/else` 语句和 `switch` 语句的使用。 6. 熟练掌握 `while` 语句、`do/while` 语句和 `for` 语句的使用以及区别。 7. 掌握 `break` 和 `continue` 程序控制语句的使用。 8. 理解并掌握如何模块化的用函数来构建程序。 9. 掌握定义函数的方法,了解函数的重载方法,了解内联函数的机制。 10. 掌握函数间传递信息的机制。 11. 掌握函数的嵌套调用(和递归调用)的方法。 # 实验设备 * 联想小新 Pro 13 2020 锐龙版笔记本电脑一台 * CPU: AMD Ryzen 7 4800U with Radeon Graphics 1.80 GHz * RAM: 16 GB # 实验内容 ## (一)、 1. `<1>` 该程序的功能是将输入的大写字符转换为小写、将输入的小写字符转换为大写 2. `<2>` 测试: | 输入 | 输出 | | --------- | ---- | | 100 40 | 0, 1 | | 2000 3000 | 1, 0 | | 1000 1000 | 0, 1 | | 2000 300 | 1, 1 | | 100 4000 | 0, 0 | 分析: 输出的第一个数表示输入的第一个数是否大于 1000 输出的第二个数表示输入的第二个数是否小于第一个数 当输入为 `1000 1000` 时,输出为 `0, 1`,这是因为 `float` 类型存在精度损失 3. `<3>` 测试: 输出为输入加一 分析: 由于大于等于 `10` 时输出时所使用的为后缀自减,故输出为原数字加一,这与小于 `10` 时的输出相同。 4. `<4>` 使用的为 `辗转相减法(更相减损术)` 5. `<5>` 测试: 输出:`22---10` 分析: 该程序的功能为对 `m` 和 `n` 做整除和取余运算;输出中的 `k` 是进行除法运算的整除结果,`m` 是余数 6. `<6>` 当 `i` 为奇数时输出星号和井号 7. `<7>` 测试: 输出:`a=2, b=8` 分析: 进行了一次循环;若改为 `while`,则循环将进行 `0` 次 8. `<5>` `hfc()` 函数表示求最大公因数 `lcd()` 函数表示求最小公倍数 测试: 输入:`1 10` 输出:`hfc=1 lcd=10` 9. `<6>` `fib()` 函数的功能为求斐波拉契数列的第 `n` 项 斐波拉契数列的每一项都是前两项之和 10. `<7>` 测试: ``` (2)A (3)5,6 (1)4,6 ``` 分析: `(2)` 中输出的是**局部变量** `k` `(3)` 中输出的是**全局变量** `k` `(1)` 中输出的是**全局变量** `k` 11. `<8>` 测试: ``` subp函数输出: 1 1 0 0 main函数输出: 9 3 6 12 subp函数输出: 2 2 1 1 ``` 分析: `x` `y` 是静态变量,只会创建一次;所以除了在第一次运行 `subp()` 函数时,都不再会初始化 `x` `y`。若把 `static` 去除,则运行结果会发生改变。因为此时 `x` `y` 不再是静态变量,每一次调用 `subp()` 函数时 `x` `y` 都会重新初始化为 `0` ## (二)、 1. 第一题(`<1>`)(2)、(4)解题分析: 此题较为简单,调用 `math.h` 库即可 ```c #include #include double T2(double x) { return sqrt(1 + 1 / (x + 1 / (x + 1))); } double T4(double x, double y) { return exp(x + y) + exp(x - y); } int main() { double x, y; scanf("%lf", &x); printf("%lf\n", T2(x)); scanf("%lf%lf", &x, &y); printf("%lf\n", T3(x, y)); } ``` 测试: ``` 输入: 1 1 2 输出: 1.290994 20.453416 ``` 2. 第二题(`<2>`)解题分析: 此题较为简单,考虑读取的是字符,将字符逆向输出即可 ```c #include int main() { char sep[4] = {'\n', ',', ',', ','}; char theNumber[4]; fread(theNumber, sizeof(char), 4, stdin); for (int i = 3; i >= 0; --i) printf("%c%c ", theNumber[i], sep[i]); } ``` 测试: ``` 输入: 1234 输出: 4, 3, 2, 1 ``` 3. 第三题(`<3>`)解题分析: 此题较为简单,调用 `math.h` 库即可 ```c #include #include double theZ(double x, double y) { if (x < 0 && y < 0) return exp(x + y); else if (1 <= x + y && x + y < 10) return log(x + y); else return log10(fabs(x + y)); } int main() { double x, y; scanf("%lf%lf", &x, &y); printf("%lf\n", theZ(x, y)); } ``` 测试: ``` 输入:1 10 输出:1.041393 ``` 4. 第五题(`<5>`)(1)、(3)解题分析: 此题较为简单,可以使用 `for` 循环,这里使用递归进行求解 ```c int T1(int i) { return i == 1 ? i : i + T1(i - 1); } long T3(long i) { return i == 2 ? i * (i - 1) : i * (i - 1) + T3(i - 2); } int main() { printf("%d\n", T1(100)); printf("%ld\n", T3(40)); } ``` 测试: ``` 5050 11060 ``` 分析: 程序如期运行,结果正确 5. 第六题(`<6>`)解题分析: 比较简单的一道题 ```c #include #define MAGIC_NUMBER 21 void print_left(int i) { for (int j = 1; j <= i; j += 2) printf(" %d ", j); } void print_right(int i) { for (int j = i - 2; j >= 1; j -= 2) printf(" %d ", j); } void print_space(int i) { for (int j = 1; j <= MAGIC_NUMBER - i - 1; j += 2) { printf(" "); } } int main() { for (int i = 1; i <= MAGIC_NUMBER; i += 2) { print_space(i); print_left(i); print_right(i); printf("\n"); } } ``` 测试 ``` 1 1 3 1 1 3 5 3 1 1 3 5 7 5 3 1 1 3 5 7 9 7 5 3 1 1 3 5 7 9 11 9 7 5 3 1 1 3 5 7 9 11 13 11 9 7 5 3 1 1 3 5 7 9 11 13 15 13 11 9 7 5 3 1 1 3 5 7 9 11 13 15 17 15 13 11 9 7 5 3 1 1 3 5 7 9 11 13 15 17 19 17 15 13 11 9 7 5 3 1 1 3 5 7 9 11 13 15 17 19 21 19 17 15 13 11 9 7 5 3 1 ``` 6. 第七题(`<7>`)题目解析: 遍历即可 ```c #include int main() { for (int i = 1; i <= 10; ++i) for (int j = 1; j < i; ++j) printf("<%d, %d>\n", i, j); } ``` 测试 ``` <2, 1> <3, 1> <3, 2> ... <10, 7> <10, 8> <10, 9> ``` 7. 第八题(`<8>`)题目解析: 暴力输出即可 ```c #include int main() { for (int i = 2; i < 10; ++i) for (int j = 1; j < i; ++j) printf("%d\n", j * 10 + i); for (int i = 3; i < 10; ++i) for (int j = 2; j < i; ++j) for (int k = 1; k < j; ++k) printf("%d\n", k * 100 + j * 10 + i); for (int i = 4; i < 10; ++i) for (int j = 3; j < i; ++j) for (int k = 2; k < j; ++k) for (int l = 1; l < k; ++l) printf("%04d\n", l * 1000 + k * 100 + j * 10 + i); } ``` 测试: ``` 12 13 23 ... 4789 5789 6789 ``` 8. 第九题(`<9>`)题目解析: 使用递归进行求解较为简单 ```c #include void find_fact(int n) { int is_fact = 1; for (int i = 2; i < n; ++i) { if (n % i == 0) { printf("%d*", i); find_fact(n / i); is_fact = 0; break; } } if (is_fact) { printf("%d", n); } } int main() { int n; scanf("%d", &n); find_fact(n); } ``` 测试: ``` 输入:16 输出:2*2*2*2 输入:15 输出:3*5 输入:200 输出:2*2*2*5*5 ``` ## (三)、 1. 第一题解题分析: 需要注意重复使用的数字 ```c #include #define LEN 12 int main() { int nums[LEN] = {1, 20, 20, 12, 3, 5, 7, 4, 6, 100, 11, 8}; int comp, t; comp = nums[1] > nums[0] ? 1 : nums[1] < nums[0] ? -1 : 0; printf("("); for (int i = 1; i < LEN; ++i) { t = nums[i] > nums[i - 1] ? 1 : nums[i] < nums[i - 1] ? -1 : 0; if (t) if (t == comp) printf("%d ", nums[i - 1]); else { printf("%d), (%d ", nums[i - 1], nums[i - 1]); comp = nums[i] > nums[i - 1] ? 1 : nums[i] < nums[i - 1] ? -1 : 0; } else comp = nums[i] > nums[i - 1] ? 1 : nums[i] < nums[i - 1] ? -1 : 0; } printf("%d)", nums[LEN - 1]); } ``` 测试: ``` (1 20), (20 12 3), (3 5 7), (7 4), (4 6 100), (100 11 8) ``` 2. 第二题解题分析: 只需反复求出后三位乘以 `12` 的结果即可 ```c #include int main() { int n = 12; for (int i = 0; i < 100; ++i) n = n % 1000 * 12; printf("%d\n", n % 1000); } ``` 测试: ``` 512 ``` # 实验总结 此次实验让我更加深入的了解了 `C++` 语言的特性,学习了许多 `C++` 语言更深入的用法及技巧,对于函数和递归有了更深一步的认识,也对编程有了新的体会。 在完成 `T10` 时,本地编译出现了错误;经排错发现为报告代码出现问题。将代码中 `int fun(int) `的声明修改为 `void fun(int)` 后编译通过。通过此测试了解到了 `C++` 语言中声明应与实现一致。 # 参考资料 1. 参考了 `C17` 标准 2. [C Plus Plus Reference](https://zh.cppreference.com)