diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-09-24 19:22:15 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-09-24 19:22:15 +0800 |
| commit | 679fa4f220c40e552d4ba4e67669680f10c21a6d (patch) | |
| tree | 8d034761edc23e450577126f928a474c80b6ca0d | |
| download | RUCDSA-679fa4f220c40e552d4ba4e67669680f10c21a6d.tar.gz RUCDSA-679fa4f220c40e552d4ba4e67669680f10c21a6d.tar.xz | |
lab01
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | lab01/1.in | 3 | ||||
| -rw-r--r-- | lab01/1.out | 1 | ||||
| -rw-r--r-- | lab01/10.in | 2 | ||||
| -rw-r--r-- | lab01/10.out | 1 | ||||
| -rw-r--r-- | lab01/2.in | 3 | ||||
| -rw-r--r-- | lab01/2.out | 1 | ||||
| -rw-r--r-- | lab01/3.in | 3 | ||||
| -rw-r--r-- | lab01/3.out | 1 | ||||
| -rw-r--r-- | lab01/4.in | 3 | ||||
| -rw-r--r-- | lab01/4.out | 1 | ||||
| -rw-r--r-- | lab01/5.in | 3 | ||||
| -rw-r--r-- | lab01/5.out | 1 | ||||
| -rw-r--r-- | lab01/6.in | 3 | ||||
| -rw-r--r-- | lab01/6.out | 1 | ||||
| -rw-r--r-- | lab01/7.in | 2 | ||||
| -rw-r--r-- | lab01/7.out | 1 | ||||
| -rw-r--r-- | lab01/8.in | 2 | ||||
| -rw-r--r-- | lab01/8.out | 1 | ||||
| -rw-r--r-- | lab01/9.in | 2 | ||||
| -rw-r--r-- | lab01/9.out | 1 | ||||
| -rw-r--r-- | lab01/Makefile | 51 | ||||
| -rw-r--r-- | lab01/Triplet.hh | 91 | ||||
| -rw-r--r-- | lab01/main.cc | 142 | ||||
| -rw-r--r-- | lab01/manual.md | 335 | ||||
| -rw-r--r-- | lab01/tests.md | 14 | ||||
| -rwxr-xr-x | lab01/triplet | bin | 0 -> 17376 bytes |
27 files changed, 671 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3d10c82 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.tar.gz + diff --git a/lab01/1.in b/lab01/1.in new file mode 100644 index 0000000..10051e2 --- /dev/null +++ b/lab01/1.in @@ -0,0 +1,3 @@ +ADD +1 2 3 +4 5 6 diff --git a/lab01/1.out b/lab01/1.out new file mode 100644 index 0000000..2739135 --- /dev/null +++ b/lab01/1.out @@ -0,0 +1 @@ +5 7 9 diff --git a/lab01/10.in b/lab01/10.in new file mode 100644 index 0000000..dbb08fd --- /dev/null +++ b/lab01/10.in @@ -0,0 +1,2 @@ +DESC +5 5 -1 diff --git a/lab01/10.out b/lab01/10.out new file mode 100644 index 0000000..27ba77d --- /dev/null +++ b/lab01/10.out @@ -0,0 +1 @@ +true diff --git a/lab01/2.in b/lab01/2.in new file mode 100644 index 0000000..5f7ff0a --- /dev/null +++ b/lab01/2.in @@ -0,0 +1,3 @@ +SUB +10 8 6 +1 2 3 diff --git a/lab01/2.out b/lab01/2.out new file mode 100644 index 0000000..d897c01 --- /dev/null +++ b/lab01/2.out @@ -0,0 +1 @@ +9 6 3 diff --git a/lab01/3.in b/lab01/3.in new file mode 100644 index 0000000..d73d155 --- /dev/null +++ b/lab01/3.in @@ -0,0 +1,3 @@ +SCALE +1 2 3 +5 diff --git a/lab01/3.out b/lab01/3.out new file mode 100644 index 0000000..a396b14 --- /dev/null +++ b/lab01/3.out @@ -0,0 +1 @@ +5 10 15 diff --git a/lab01/4.in b/lab01/4.in new file mode 100644 index 0000000..5e01034 --- /dev/null +++ b/lab01/4.in @@ -0,0 +1,3 @@ +SCALE +-2 1 4 +-3 diff --git a/lab01/4.out b/lab01/4.out new file mode 100644 index 0000000..3e00bb6 --- /dev/null +++ b/lab01/4.out @@ -0,0 +1 @@ +6 -3 -12 diff --git a/lab01/5.in b/lab01/5.in new file mode 100644 index 0000000..4567ff8 --- /dev/null +++ b/lab01/5.in @@ -0,0 +1,3 @@ +DOT +1 2 3 +4 5 6 diff --git a/lab01/5.out b/lab01/5.out new file mode 100644 index 0000000..f5c8955 --- /dev/null +++ b/lab01/5.out @@ -0,0 +1 @@ +32 diff --git a/lab01/6.in b/lab01/6.in new file mode 100644 index 0000000..1fcb8ed --- /dev/null +++ b/lab01/6.in @@ -0,0 +1,3 @@ +DOT +1 -2 3 +-4 5 -6 diff --git a/lab01/6.out b/lab01/6.out new file mode 100644 index 0000000..078f335 --- /dev/null +++ b/lab01/6.out @@ -0,0 +1 @@ +-32 diff --git a/lab01/7.in b/lab01/7.in new file mode 100644 index 0000000..2c0a990 --- /dev/null +++ b/lab01/7.in @@ -0,0 +1,2 @@ +MAX +-5 12 7 diff --git a/lab01/7.out b/lab01/7.out new file mode 100644 index 0000000..48082f7 --- /dev/null +++ b/lab01/7.out @@ -0,0 +1 @@ +12 diff --git a/lab01/8.in b/lab01/8.in new file mode 100644 index 0000000..2f6f823 --- /dev/null +++ b/lab01/8.in @@ -0,0 +1,2 @@ +ASC +1 2 2 diff --git a/lab01/8.out b/lab01/8.out new file mode 100644 index 0000000..27ba77d --- /dev/null +++ b/lab01/8.out @@ -0,0 +1 @@ +true diff --git a/lab01/9.in b/lab01/9.in new file mode 100644 index 0000000..3d6737b --- /dev/null +++ b/lab01/9.in @@ -0,0 +1,2 @@ +ASC +3 2 1 diff --git a/lab01/9.out b/lab01/9.out new file mode 100644 index 0000000..c508d53 --- /dev/null +++ b/lab01/9.out @@ -0,0 +1 @@ +false diff --git a/lab01/Makefile b/lab01/Makefile new file mode 100644 index 0000000..527d7ed --- /dev/null +++ b/lab01/Makefile @@ -0,0 +1,51 @@ +CXX := g++ +CXXFLAGS := -std=c++11 -Wall -Wextra -Wpedantic -O2 + +TARGET := triplet +SOURCE := main.cc +HEADER := Triplet.hh + +.PHONY: build test + +build: $(TARGET) + +$(TARGET): $(SOURCE) $(HEADER) + $(CXX) $(CXXFLAGS) $(SOURCE) -o $(TARGET) + +test: build + @passed=0; \ + failed=0; \ + total=0; \ + for input in *.in; do \ + if [ ! -f "$$input" ]; then \ + continue; \ + fi; \ + total=$$((total + 1)); \ + base=$${input%.in}; \ + expected="$$base.out"; \ + actual="$$base.actual"; \ + if [ ! -f "$$expected" ]; then \ + echo "[FAIL] $$input: missing $$expected"; \ + failed=$$((failed + 1)); \ + continue; \ + fi; \ + if ./$(TARGET) < "$$input" > "$$actual"; then \ + if diff -u "$$expected" "$$actual" > /dev/null; then \ + echo "[PASS] $$base"; \ + passed=$$((passed + 1)); \ + else \ + echo "[FAIL] $$base"; \ + diff -u "$$expected" "$$actual" || true; \ + failed=$$((failed + 1)); \ + fi; \ + else \ + echo "[FAIL] $$base: program exited with an error"; \ + failed=$$((failed + 1)); \ + fi; \ + rm -f "$$actual"; \ + done; \ + echo; \ + echo "Passed: $$passed / $$total"; \ + if [ "$$failed" -ne 0 ]; then \ + exit 1; \ + fi diff --git a/lab01/Triplet.hh b/lab01/Triplet.hh new file mode 100644 index 0000000..693ede5 --- /dev/null +++ b/lab01/Triplet.hh @@ -0,0 +1,91 @@ +/* + * Triplet.hh + * + * Template implementation of the Triplet abstract data type. + * The class also provides basic three-dimensional vector operations. + */ + +#include <array> +#include <cstddef> +#include <algorithm> + +/** + * A generic three-element tuple. + * + * In this experiment, Triplet is also treated as a three-dimensional + * vector, supporting vector addition, subtraction, scalar multiplication + * and dot product. + * + * T is the element type of the triplet. + */ +template<typename T> +class Triplet { +public: + Triplet (T a, T b, T c) : data_{a, b, c} {} + + T &operator[] (std::size_t i) { + return data_[i]; + } + + const T &operator[] (std::size_t i) const + { + return data_[i]; + } + + Triplet operator+ (const Triplet &rhs) const + { + return Triplet (data_[0] + rhs.data_[0], + data_[1] + rhs.data_[1], + data_[2] + rhs.data_[2]); + } + + Triplet operator- (const Triplet &rhs) const + { + return Triplet (data_[0] - rhs.data_[0], + data_[1] - rhs.data_[1], + data_[2] - rhs.data_[2]); + } + + /* Scalar multiplication: vector * scalar. */ + Triplet operator* (const T& scalar) const + { + return Triplet( + data_[0] * scalar, + data_[1] * scalar, + data_[2] * scalar); + } + + /* Scalar multiplication: scalar * vector. */ + friend Triplet + operator* (const T &scalar, const Triplet &v) { + return v * scalar; + } + + /* Dot product of two three-dimensional vectors. */ + T operator* (const Triplet &rhs) const { + return data_[0] * rhs.data_[0] + + data_[1] * rhs.data_[1] + + data_[2] * rhs.data_[2]; + } + + T max () const { + return *std::max_element (data_.begin (), data_.end ()); + } + + T min() const { + return *std::min_element( data_.begin (), data_.end ()); + } + + /* Return true if the elements are in nondecreasing order. */ + bool is_ascending() const { + return data_[0] <= data_[1] && data_[1] <= data_[2]; + } + + /* Return true if the elements are in nonincreasing order. */ + bool is_descending() const { + return data_[0] >= data_[1] && data_[1] >= data_[2]; + } + +private: + std::array<T, 3> data_; +}; diff --git a/lab01/main.cc b/lab01/main.cc new file mode 100644 index 0000000..475f7e6 --- /dev/null +++ b/lab01/main.cc @@ -0,0 +1,142 @@ +/* + * main.cc + * + * Test driver for the Triplet class. + * Operations are read from standard input and results are written + * to standard output. + */ + +#include "Triplet.hh" + +#include <iostream> +#include <string> + + +/* + * Read one operation from standard input and execute it. + * + * Supported operations: + * + * ADD a b c x y z + * SUB a b c x y z + * SCALE a b c k + * DOT a b c x y z + * MAX a b c + * ASC a b c + * DESC a b c + * + * The result is written to standard output. + */ +int +main () +{ + std::string op; + + if (!(std::cin >> op)) + return 1; + + if (op == "ADD") + { + double a, b, c; + double x, y, z; + + if (!(std::cin >> a >> b >> c >> x >> y >> z)) + return 1; + + Triplet<double> lhs (a, b, c); + Triplet<double> rhs (x, y, z); + Triplet<double> result = lhs + rhs; + + std::cout << result[0] << ' ' + << result[1] << ' ' + << result[2] << '\n'; + } + else if (op == "SUB") + { + double a, b, c; + double x, y, z; + + if (!(std::cin >> a >> b >> c >> x >> y >> z)) + return 1; + + Triplet<double> lhs (a, b, c); + Triplet<double> rhs (x, y, z); + Triplet<double> result = lhs - rhs; + + std::cout << result[0] << ' ' + << result[1] << ' ' + << result[2] << '\n'; + } + else if (op == "SCALE") + { + double a, b, c; + double scalar; + + if (!(std::cin >> a >> b >> c >> scalar)) + return 1; + + Triplet<double> v (a, b, c); + Triplet<double> result = v * scalar; + + std::cout << result[0] << ' ' + << result[1] << ' ' + << result[2] << '\n'; + } + else if (op == "DOT") + { + double a, b, c; + double x, y, z; + + if (!(std::cin >> a >> b >> c >> x >> y >> z)) + return 1; + + Triplet<double> lhs (a, b, c); + Triplet<double> rhs (x, y, z); + + std::cout << lhs * rhs << '\n'; + } + else if (op == "MAX") + { + double a, b, c; + + if (!(std::cin >> a >> b >> c)) + return 1; + + Triplet<double> v (a, b, c); + + std::cout << v.max () << '\n'; + } + else if (op == "ASC") + { + double a, b, c; + + if (!(std::cin >> a >> b >> c)) + return 1; + + Triplet<double> v (a, b, c); + + std::cout << std::boolalpha + << v.is_ascending () + << '\n'; + } + else if (op == "DESC") + { + double a, b, c; + + if (!(std::cin >> a >> b >> c)) + return 1; + + Triplet<double> v (a, b, c); + + std::cout << std::boolalpha + << v.is_descending () + << '\n'; + } + else + { + std::cerr << "Unknown operation: " << op << '\n'; + return 1; + } + + return 0; +} diff --git a/lab01/manual.md b/lab01/manual.md new file mode 100644 index 0000000..5a88996 --- /dev/null +++ b/lab01/manual.md @@ -0,0 +1,335 @@ +# 实验 01:三元组程序使用手册 + +## 1. 程序简介 + +本程序使用 C++ 实现三元组(`Triplet`)数据类型,并将三元组视为三维向量进行基本运算。`Triplet` 使用模板实现,可以保存不同类型的元素;实验程序的标准输入测试部分使用 `Triplet<double>`。 + +程序支持三元组加法、三元组减法、标量乘法、三元组点积、求最大元素、判断非递减顺序以及判断非递增顺序。程序通过标准输入读取操作名称和数据,并将结果写入标准输出。程序本身不输出交互式提示信息,便于使用输入文件进行自动测试。 + +## 2. 文件说明 + +项目主要文件如下: + +```text +. +├── main.cc +├── Triplet.hh +├── Makefile +├── 1.in +├── 1.out +├── 2.in +├── 2.out +└── ... +``` + +其中,`Triplet.hh` 保存三元组模板类的定义与实现;`main.cc` 是程序入口,负责读取输入、识别操作并输出结果;`Makefile` 提供编译和自动测试功能;`*.in` 为测试输入文件;`*.out` 为对应的期望输出文件。 + +## 3. 编译环境 + +推荐使用 GNU/Linux、Unix 类系统,或具有 GNU 工具链的 Windows 环境。编译器使用 GCC/G++,C++ 标准为 C++11,构建工具使用 GNU Make。 + +建议编译选项: + +```text +-std=c++11 -Wall -Wextra -Wpedantic -O2 +``` + +其中,`-std=c++11` 指定 C++11 标准;`-Wall -Wextra -Wpedantic` 启用常用编译警告;`-O2` 启用常规优化。 + +## 4. 编译程序 + +在项目目录执行: + +```bash +make build +``` + +编译成功后生成可执行文件: + +```text +triplet +``` + +也可以直接使用 `g++` 编译: + +```bash +g++ -std=c++11 -Wall -Wextra -Wpedantic -O2 main.cc -o triplet +``` + +## 5. 运行方式 + +程序一次处理一个操作。输入的第一个字符串表示操作类型,后续数据格式由操作决定。 + +直接运行: + +```bash +./triplet +``` + +也可以通过输入重定向运行: + +```bash +./triplet < test01.in +``` + +## 6. 输入与输出格式 + +### 6.1 加法 `ADD` + +输入两个三元组,计算对应分量之和。 + +```text +ADD +a1 a2 a3 +b1 b2 b3 +``` + +示例输入: + +```text +ADD +1 2 3 +4 5 6 +``` + +输出: + +```text +5 7 9 +``` + +### 6.2 减法 `SUB` + +输入两个三元组,计算第一个三元组减去第二个三元组。 + +```text +SUB +a1 a2 a3 +b1 b2 b3 +``` + +示例输入: + +```text +SUB +10 8 6 +1 2 3 +``` + +输出: + +```text +9 6 3 +``` + +### 6.3 标量乘法 `SCALE` + +输入一个三元组和一个标量,将三元组的每个分量乘以该标量。 + +```text +SCALE +a1 a2 a3 +k +``` + +示例输入: + +```text +SCALE +1 2 3 +5 +``` + +输出: + +```text +5 10 15 +``` + +### 6.4 点积 `DOT` + +输入两个三元组,计算三维向量点积: + +```text +a1*b1 + a2*b2 + a3*b3 +``` + +输入格式: + +```text +DOT +a1 a2 a3 +b1 b2 b3 +``` + +示例输入: + +```text +DOT +1 2 3 +4 5 6 +``` + +输出: + +```text +32 +``` + +### 6.5 最大值 `MAX` + +输入一个三元组,输出其中最大的元素。 + +```text +MAX +a1 a2 a3 +``` + +示例输入: + +```text +MAX +-5 12 7 +``` + +输出: + +```text +12 +``` + +### 6.6 非递减判断 `ASC` + +判断三元组是否满足: + +```text +a1 <= a2 <= a3 +``` + +输入格式: + +```text +ASC +a1 a2 a3 +``` + +示例输入: + +```text +ASC +1 2 2 +``` + +输出: + +```text +true +``` + +若不满足条件,则输出: + +```text +false +``` + +### 6.7 非递增判断 `DESC` + +判断三元组是否满足: + +```text +a1 >= a2 >= a3 +``` + +输入格式: + +```text +DESC +a1 a2 a3 +``` + +示例输入: + +```text +DESC +5 5 -1 +``` + +输出: + +```text +true +``` + +若不满足条件,则输出: + +```text +false +``` + +## 7. 输入格式说明 + +程序使用 `std::cin` 读取数据,因此空格、换行和制表符都可以作为分隔符。以下两种输入形式等价: + +```text +ADD +1 2 3 +4 5 6 +``` + +```text +ADD 1 2 3 4 5 6 +``` + +为了便于阅读和整理测试用例,建议每个三元组单独占一行。 + +## 8. 自动测试 + +项目中的 `Makefile` 提供自动测试目标: + +```bash +make test +``` + +执行后,`Makefile` 会自动扫描当前目录中的所有 `*.in` 文件。对于每个输入文件,例如 `1.in`,程序执行: + +```bash +./triplet < 1.in +``` + +并将实际输出与对应的 `1.out` 进行比较。 + +测试通过时输出类似: + +```text +[PASS] 1 +``` + +测试失败时输出类似: + +```text +[FAIL] 1 +``` + +同时显示实际输出和期望输出之间的差异。全部测试完成后显示统计结果,例如: + +```text +Passed: 10 / 10 +``` + +## 9. 返回状态 + +程序正常完成操作时返回 `0`。标准输入中没有操作名称、输入数据数量不足、格式错误或操作名称不受支持时,程序返回非零状态。 + +对于未知操作,程序会向标准错误流输出错误信息并结束。例如: + +```text +UNKNOWN +``` + +## 10. 注意事项 + +1. 操作名称区分大小写,应使用 `ADD`、`SUB`、`SCALE`、`DOT`、`MAX`、`ASC`、`DESC`。 +2. 当前测试程序使用 `double` 作为三元组元素类型,因此整数和小数都可以输入。 +3. `ASC` 和 `DESC` 使用非严格比较,因此相邻元素相等时仍可能返回 `true`。 +4. 每次程序运行只处理一个操作。 +5. 自动测试要求输入文件和输出文件使用相同的文件名前缀,例如 `test01.in` 对应 `test01.out`。 diff --git a/lab01/tests.md b/lab01/tests.md new file mode 100644 index 0000000..80b1306 --- /dev/null +++ b/lab01/tests.md @@ -0,0 +1,14 @@ +# 测试用例说明 + +| 编号 | 操作 | 测试内容 | +|---|---|---| +| test01 | ADD | 测试两个普通三元组的加法 | +| test02 | SUB | 测试三元组减法 | +| test03 | SCALE | 测试正数标量乘法 | +| test04 | SCALE | 测试负数标量乘法 | +| test05 | DOT | 测试普通点积 | +| test06 | DOT | 测试包含负数的点积 | +| test07 | MAX | 测试最大元素查找 | +| test08 | ASC | 测试包含相等元素的非递减序列 | +| test09 | ASC | 测试非升序情况 | +| test10 | DESC | 测试包含相等元素的非递增序列 | diff --git a/lab01/triplet b/lab01/triplet Binary files differnew file mode 100755 index 0000000..a733b7d --- /dev/null +++ b/lab01/triplet |
