summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-09-24 19:22:15 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-09-24 19:22:15 +0800
commit679fa4f220c40e552d4ba4e67669680f10c21a6d (patch)
tree8d034761edc23e450577126f928a474c80b6ca0d
downloadRUCDSA-679fa4f220c40e552d4ba4e67669680f10c21a6d.tar.gz
RUCDSA-679fa4f220c40e552d4ba4e67669680f10c21a6d.tar.xz
lab01
-rw-r--r--.gitignore2
-rw-r--r--lab01/1.in3
-rw-r--r--lab01/1.out1
-rw-r--r--lab01/10.in2
-rw-r--r--lab01/10.out1
-rw-r--r--lab01/2.in3
-rw-r--r--lab01/2.out1
-rw-r--r--lab01/3.in3
-rw-r--r--lab01/3.out1
-rw-r--r--lab01/4.in3
-rw-r--r--lab01/4.out1
-rw-r--r--lab01/5.in3
-rw-r--r--lab01/5.out1
-rw-r--r--lab01/6.in3
-rw-r--r--lab01/6.out1
-rw-r--r--lab01/7.in2
-rw-r--r--lab01/7.out1
-rw-r--r--lab01/8.in2
-rw-r--r--lab01/8.out1
-rw-r--r--lab01/9.in2
-rw-r--r--lab01/9.out1
-rw-r--r--lab01/Makefile51
-rw-r--r--lab01/Triplet.hh91
-rw-r--r--lab01/main.cc142
-rw-r--r--lab01/manual.md335
-rw-r--r--lab01/tests.md14
-rwxr-xr-xlab01/tripletbin0 -> 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
new file mode 100755
index 0000000..a733b7d
--- /dev/null
+++ b/lab01/triplet
Binary files differ