upgrade to python3;add some validator examples

This commit is contained in:
2025-10-11 12:33:24 +08:00
parent 65632f0e60
commit 487c041148
25 changed files with 1492 additions and 317 deletions

View File

@@ -0,0 +1,295 @@
# BitOJ 自定义验证程序完整指南
## 概述
BitOJ系统支持4种判题方式
1. **字符串精确比较** - 逐字符对比输出
2. **字符串容错比较** - 允许格式错误(PE),主要比较数字内容
3. **文件MD5校验** - 比较文件大小和MD5值
4. **自定义验证程序** - 编写专门的验证逻辑
本文档重点介绍第4种方式自定义验证程序的编写和使用。
## 自定义验证程序原理
### 工作流程
1. 系统执行用户提交的代码
2. 将输入、期望输出、实际输出传递给验证程序
3. 验证程序分析这些文件并返回判题结果
4. 系统根据返回结果确定最终评分
### 参数说明
验证程序接收以下参数:
- `argv[1]`: 标准输入文件路径
- `argv[2]`: 期望输出文件路径
- `argv[3]`: 用户程序输出文件路径
### 返回值
验证程序必须输出以下结果之一:
- `AC` - Accepted答案正确
- `PE` - Presentation Error格式错误
- `WA` - Wrong Answer答案错误
## 实际示例
### 1. 浮点数误差比较 (C++)
**适用场景**: 计算几何、数值计算等需要浮点数比较的题目
```cpp
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;
const double EPS = 1e-9;
int main(int argc, char* argv[]) {
ifstream expected(argv[2]); // 标准答案
ifstream result(argv[3]); // 用户输出
double exp_val, res_val;
if (!(expected >> exp_val) || !(result >> res_val)) {
cout << "WA" << endl;
return 0;
}
if (fabs(exp_val - res_val) <= EPS) {
cout << "AC" << endl;
} else {
cout << "WA" << endl;
}
return 0;
}
```
### 2. 多解答案验证 (Python)
**适用场景**: 排序题、图论路径题等有多种正确答案的题目
```python
#!/usr/bin/env python
import sys
def main():
try:
with open(sys.argv[2], 'r') as f:
expected = f.read().strip()
with open(sys.argv[3], 'r') as f:
result = f.read().strip()
# 解析数字并排序比较
expected_nums = sorted(map(int, expected.split()))
result_nums = sorted(map(int, result.split()))
if expected_nums == result_nums:
print("AC")
else:
print("WA")
except:
print("WA")
if __name__ == "__main__":
main()
```
### 3. 输出格式验证 (Java)
**适用场景**: 需要严格输出格式的竞赛题目
```java
import java.io.*;
import java.util.*;
import java.util.regex.Pattern;
public class StringFormatValidator {
public static void main(String[] args) {
try {
Scanner result = new Scanner(new File(args[2]));
int lineNum = 1;
while (result.hasNextLine()) {
String line = result.nextLine().trim();
// 检查格式Case #X: Y
Pattern pattern = Pattern.compile("^Case #" + lineNum + ": \\d+$");
if (!pattern.matcher(line).matches()) {
System.out.println("PE");
return;
}
lineNum++;
}
System.out.println("AC");
} catch (Exception e) {
System.out.println("WA");
}
}
}
```
## 在BitOJ中配置自定义验证程序
### 代码配置示例
```python
from judgescript import ExternalJudge
# 创建自定义验证程序
validator = ExternalJudge(
problemid='P1001', # 题目ID
vlang='gcc-3.3', # 验证程序语言
vcode=validator_code # 验证程序源代码
)
# 在测试过程中调用
result = validator.judge(
sid='S123', # 提交ID
tid='T001', # 测试用例ID
tin='/path/to/input.txt', # 输入文件
tout='/path/to/output.txt', # 期望输出
result='/path/to/result.txt', # 实际输出
errfile='/path/to/error.txt' # 错误输出
)
```
### 支持的编程语言
| 语言 | 标识符 | 说明 |
|------|--------|------|
| C | gcc-3.3 | 适合高性能验证 |
| C++ | g++-3.3 | 支持STL容器 |
| Java | java-1.6 | 强类型安全 |
| Python | python-2.5 | 快速开发 |
| Pascal | fpc-2.2 | 简单逻辑 |
## 最佳实践
### 1. 错误处理
```cpp
// 文件读取失败处理
if (!input_file.is_open()) {
cout << "WA" << endl;
return 0;
}
// 数据解析失败处理
try {
value = stod(line);
} catch (const exception& e) {
cout << "WA" << endl;
return 0;
}
```
### 2. 性能优化
- 使用适当的数据结构
- 避免不必要的字符串操作
- 合理设置缓冲区大小
- 注意内存使用限制
### 3. 安全考虑
- 验证输入参数数量
- 处理异常文件路径
- 限制递归深度
- 避免无限循环
### 4. 可维护性
- 添加清晰的注释
- 使用有意义的变量名
- 模块化验证逻辑
- 提供调试输出选项
## 常见应用场景
### 1. 数值计算题
- 浮点数精度比较
- 矩阵运算结果验证
- 统计数值的近似比较
### 2. 图论算法题
- 最短路径验证(允许多条等长路径)
- 最小生成树验证(权重相等即可)
- 图遍历结果验证
### 3. 字符串处理题
- 忽略大小写比较
- 忽略空白字符差异
- 正则表达式匹配
### 4. 组合数学题
- 排列组合结果验证
- 集合操作结果比较
- 数学证明步骤检查
### 5. 交互式题目
- 模拟交互过程
- 验证查询次数限制
- 检查答案正确性
## 调试技巧
### 1. 本地测试
```bash
# 编译验证程序
g++ -o validator validator.cpp
# 准备测试文件
echo "3.14159" > expected.txt
echo "3.14160" > result.txt
# 运行测试
./validator input.txt expected.txt result.txt
```
### 2. 日志输出
```cpp
#ifdef DEBUG
cerr << "Expected: " << exp_val << ", Got: " << res_val << endl;
cerr << "Difference: " << fabs(exp_val - res_val) << endl;
#endif
```
### 3. 边界情况测试
- 空输出文件
- 超大数值
- 特殊字符
- 格式错误的输入
## 故障排除
### 常见问题
1. **编译失败**
- 检查语言版本兼容性
- 确认头文件引用正确
- 验证语法错误
2. **运行超时**
- 优化算法复杂度
- 减少不必要的计算
- 检查是否有死循环
3. **内存不足**
- 减少内存分配
- 及时释放资源
- 使用流式处理
4. **判题结果异常**
- 验证输出格式
- 检查返回值规范
- 确认异常处理逻辑
## 总结
自定义验证程序是BitOJ系统最灵活的判题方式能够处理各种复杂的判题需求。通过合理设计验证逻辑可以支持
- 多解答案题目
- 浮点数精度要求
- 特殊输出格式
- 交互式评测
- 复杂的正确性检查
掌握自定义验证程序的编写技巧,能够大大扩展在线评测系统的应用范围,为各种类型的编程竞赛和教学需求提供支持。

View File

@@ -0,0 +1,69 @@
/*
* 字符串格式验证程序
* 验证输出是否符合特定格式要求
* 编译: javac StringFormatValidator.java
* 使用: java StringFormatValidator input.txt expected.txt result.txt
*/
import java.io.*;
import java.util.*;
import java.util.regex.Pattern;
public class StringFormatValidator {
public static void main(String[] args) {
if (args.length != 3) {
System.out.println("WA");
return;
}
try {
// 读取期望的行数和格式信息
Scanner expected = new Scanner(new File(args[1]));
Scanner result = new Scanner(new File(args[2]));
// 假设期望文件第一行是期望的行数
int expectedLines = expected.nextInt();
expected.nextLine(); // 消费换行符
// 读取用户输出
List<String> userLines = new ArrayList<>();
while (result.hasNextLine()) {
String line = result.nextLine().trim();
if (!line.isEmpty()) {
userLines.add(line);
}
}
// 检查行数
if (userLines.size() != expectedLines) {
System.out.println("WA");
return;
}
// 检查每行格式
boolean formatCorrect = true;
for (int i = 0; i < userLines.size(); i++) {
String line = userLines.get(i);
// 检查是否符合 "Case #X: Y" 格式
Pattern pattern = Pattern.compile("^Case #" + (i + 1) + ": \\d+$");
if (!pattern.matcher(line).matches()) {
formatCorrect = false;
break;
}
}
if (formatCorrect) {
System.out.println("AC");
} else {
System.out.println("PE"); // 格式错误
}
expected.close();
result.close();
} catch (Exception e) {
System.out.println("WA");
}
}
}

View File

@@ -0,0 +1,328 @@
# BitOJ 自定义验证程序示例
## 1. 基本验证程序结构
自定义验证程序接收以下参数:
- 标准输入文件
- 标准输出文件(期望答案)
- 用户输出文件(用户程序的输出)
验证程序需要输出以下结果之一:
- `AC` - 答案正确
- `PE` - 格式错误(如果支持)
- `WA` - 答案错误
## 2. 示例1数值误差比较验证程序C++
适用于需要浮点数比较的题目:
```cpp
#include <iostream>
#include <fstream>
#include <cmath>
#include <string>
using namespace std;
const double EPS = 1e-9;
int main(int argc, char* argv[]) {
// argv[1]: 标准输入文件
// argv[2]: 标准输出文件
// argv[3]: 用户输出文件
ifstream expected(argv[2]); // 标准答案
ifstream result(argv[3]); // 用户输出
double exp_val, res_val;
// 读取期望的浮点数
if (!(expected >> exp_val)) {
cout << "WA" << endl;
return 0;
}
// 读取用户输出的浮点数
if (!(result >> res_val)) {
cout << "WA" << endl;
return 0;
}
// 比较数值,允许误差
if (fabs(exp_val - res_val) <= EPS) {
cout << "AC" << endl;
} else {
cout << "WA" << endl;
}
return 0;
}
```
## 3. 示例2多解答案验证程序Python
适用于有多个正确答案的题目:
```python
#!/usr/bin/env python
import sys
def main():
# sys.argv[1]: 标准输入文件
# sys.argv[2]: 标准输出文件
# sys.argv[3]: 用户输出文件
try:
with open(sys.argv[2], 'r') as f:
expected = f.read().strip()
with open(sys.argv[3], 'r') as f:
result = f.read().strip()
# 假设这是一个排序题目,任何正确的排序都是对的
expected_nums = list(map(int, expected.split()))
result_nums = list(map(int, result.split()))
# 检查数量是否相同
if len(expected_nums) != len(result_nums):
print("WA")
return
# 检查排序后是否相同(原始数据相同)
if sorted(expected_nums) != sorted(result_nums):
print("WA")
return
# 检查用户输出是否有序
if result_nums == sorted(result_nums):
print("AC")
else:
print("WA")
except Exception as e:
print("WA")
if __name__ == "__main__":
main()
```
## 4. 示例3图论路径验证程序C++
验证最短路径问题,检查路径是否合法且最优:
```cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;
struct Edge {
int to, weight;
};
int main(int argc, char* argv[]) {
ifstream input(argv[1]); // 输入数据
ifstream expected(argv[2]); // 期望答案
ifstream result(argv[3]); // 用户答案
// 读取图的信息
int n, m;
input >> n >> m;
vector<vector<Edge>> graph(n + 1);
for (int i = 0; i < m; i++) {
int u, v, w;
input >> u >> v >> w;
graph[u].push_back({v, w});
graph[v].push_back({u, w}); // 无向图
}
int start, end;
input >> start >> end;
// 读取期望的最短距离
int expected_dist;
expected >> expected_dist;
// 读取用户输出的路径
string line;
getline(result, line);
istringstream iss(line);
vector<int> path;
int node;
while (iss >> node) {
path.push_back(node);
}
// 验证路径
if (path.empty() || path[0] != start || path.back() != end) {
cout << "WA" << endl;
return 0;
}
// 计算路径长度
int total_dist = 0;
for (int i = 0; i < path.size() - 1; i++) {
int u = path[i], v = path[i + 1];
bool found = false;
for (const Edge& e : graph[u]) {
if (e.to == v) {
total_dist += e.weight;
found = true;
break;
}
}
if (!found) {
cout << "WA" << endl; // 路径不存在
return 0;
}
}
// 检查是否是最短路径
if (total_dist == expected_dist) {
cout << "AC" << endl;
} else {
cout << "WA" << endl;
}
return 0;
}
```
## 5. 示例4字符串格式验证程序Java
验证输出格式是否正确:
```java
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
// args[0]: 标准输入文件
// args[1]: 标准输出文件
// args[2]: 用户输出文件
Scanner expected = new Scanner(new File(args[1]));
Scanner result = new Scanner(new File(args[2]));
try {
// 读取期望的行数
int expectedLines = expected.nextInt();
// 检查用户输出的行数
int actualLines = 0;
List<String> userLines = new ArrayList<>();
while (result.hasNextLine()) {
String line = result.nextLine().trim();
if (!line.isEmpty()) {
userLines.add(line);
actualLines++;
}
}
if (actualLines != expectedLines) {
System.out.println("WA");
return;
}
// 检查每行格式:必须是 "Case #X: Y" 的格式
for (int i = 0; i < userLines.size(); i++) {
String line = userLines.get(i);
String pattern = "Case #" + (i + 1) + ": \\d+";
if (!line.matches(pattern)) {
System.out.println("PE"); // 格式错误
return;
}
}
System.out.println("AC");
} catch (Exception e) {
System.out.println("WA");
} finally {
expected.close();
result.close();
}
}
}
```
## 6. 示例5交互式题目验证程序C++
模拟交互过程:
```cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
int main(int argc, char* argv[]) {
ifstream input(argv[1]); // 输入数据
ifstream expected(argv[2]); // 期望的查询次数等
ifstream result(argv[3]); // 用户的查询序列
// 读取隐藏的数字
int secret;
input >> secret;
// 读取最大查询次数
int maxQueries;
expected >> maxQueries;
// 模拟交互过程
int queryCount = 0;
int guess;
bool found = false;
while (result >> guess && queryCount < maxQueries) {
queryCount++;
if (guess == secret) {
found = true;
break;
}
// 在实际交互中,这里会给用户反馈 "too high" 或 "too low"
}
// 检查结果
if (found && queryCount <= maxQueries) {
cout << "AC" << endl;
} else {
cout << "WA" << endl;
}
return 0;
}
```
## 使用方法
1. **编写验证程序**:选择合适的编程语言编写验证逻辑
2. **设置题目**:在题目配置中指定使用自定义验证程序
3. **上传验证代码**:将验证程序代码保存到系统中
4. **测试验证**:确保验证程序能正确处理各种情况
## 注意事项
1. **异常处理**:验证程序必须处理所有可能的异常情况
2. **性能考虑**:验证程序也有时间限制,需要高效实现
3. **输出格式**:验证程序必须严格按照 AC/PE/WA 格式输出
4. **安全性**:验证程序在沙箱环境中运行,有资源限制
5. **可移植性**:确保验证程序在评测环境中能正常编译运行
## 配置示例
在 BitOJ 中配置自定义验证程序:
```python
# 在题目配置中设置自定义验证程序
problem.validator_language = 'gcc-3.3' # 验证程序语言
problem.validator_code = '''
// 这里放置验证程序的源代码
'''
```

View File

@@ -0,0 +1,54 @@
// 浮点数误差比较验证程序
// 编译: g++ -o float_validator float_validator.cpp
// 使用: ./float_validator input.txt expected.txt result.txt
#include <iostream>
#include <fstream>
#include <cmath>
#include <iomanip>
using namespace std;
const double EPS = 1e-9;
int main(int argc, char* argv[]) {
if (argc != 4) {
cout << "WA" << endl;
return 0;
}
ifstream expected(argv[2]); // 标准答案
ifstream result(argv[3]); // 用户输出
if (!expected.is_open() || !result.is_open()) {
cout << "WA" << endl;
return 0;
}
double exp_val, res_val;
// 读取期望的浮点数
if (!(expected >> exp_val)) {
cout << "WA" << endl;
return 0;
}
// 读取用户输出的浮点数
if (!(result >> res_val)) {
cout << "WA" << endl;
return 0;
}
// 比较数值,允许相对误差和绝对误差
double diff = fabs(exp_val - res_val);
double rel_error = (fabs(exp_val) > EPS) ? diff / fabs(exp_val) : diff;
if (diff <= 1e-6 || rel_error <= 1e-6) { // 放宽误差范围
cout << "AC" << endl;
} else {
cout << "WA" << endl;
}
expected.close();
result.close();
return 0;
}

View File

@@ -0,0 +1,183 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
BitOJ 自定义验证程序集成示例
演示如何在实际的BitOJ系统中使用自定义验证程序
"""
import sys
sys.path.append('../python')
try:
from judgescript import InternalJudge
except ImportError:
# 如果无法导入,创建一个模拟的类
class InternalJudge:
def __init__(self, allowpe=False):
self.allowpe = allowpe
def compare_string(self, output, result):
if output == result:
return 'AC'
if self.allowpe:
# 简化的PE检查
if ''.join(output.split()) == ''.join(result.split()):
return 'PE'
return 'WA'
def demo_internal_judge():
"""演示内置判题器的使用"""
print("=== 内置判题器演示 ===")
# 标准文本比较
ij_strict = InternalJudge(allowpe=False)
print("严格文本比较:")
result = ij_strict.compare_string("hello world\n", "hello world\n")
print(f" 'hello world\\n' vs 'hello world\\n' => {result}")
result = ij_strict.compare_string("hello world", "hello world\n")
print(f" 'hello world' vs 'hello world\\n' => {result}")
# 允许格式错误的比较
ij_pe = InternalJudge(allowpe=True)
print("\n允许格式错误的比较:")
result = ij_pe.compare_string("1 2 3 4 5\n", "1\n2\n3\n4\n5\n")
print(f" '1 2 3 4 5\\n' vs '1\\n2\\n3\\n4\\n5\\n' => {result}")
result = ij_pe.compare_string("12345\n", "1 2 3 4 5\n")
print(f" '12345\\n' vs '1 2 3 4 5\\n' => {result}")
def demo_custom_judge_config():
"""演示如何配置自定义验证程序"""
print("\n=== 自定义验证程序配置示例 ===")
# 浮点数比较验证程序代码
float_validator_code = """
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;
const double EPS = 1e-9;
int main(int argc, char* argv[]) {
if (argc != 4) {
cout << "WA" << endl;
return 0;
}
ifstream expected(argv[2]);
ifstream result(argv[3]);
double exp_val, res_val;
if (!(expected >> exp_val) || !(result >> res_val)) {
cout << "WA" << endl;
return 0;
}
if (fabs(exp_val - res_val) <= EPS) {
cout << "AC" << endl;
} else {
cout << "WA" << endl;
}
return 0;
}
"""
print("浮点数比较验证程序配置:")
print(" 语言: gcc-3.3")
print(" 代码长度:", len(float_validator_code), "字符")
print(" 功能: 允许浮点数误差比较")
# 多解验证程序代码
multi_solution_code = """
import sys
def main():
try:
with open(sys.argv[2], 'r') as f:
expected = f.read().strip()
with open(sys.argv[3], 'r') as f:
result = f.read().strip()
exp_nums = sorted(map(int, expected.split()))
res_nums = sorted(map(int, result.split()))
if exp_nums == res_nums:
print("AC")
else:
print("WA")
except:
print("WA")
if __name__ == "__main__":
main()
"""
print("\n多解验证程序配置:")
print(" 语言: python-2.5")
print(" 代码长度:", len(multi_solution_code), "字符")
print(" 功能: 允许多种正确答案")
def demo_judge_usage_scenarios():
"""演示不同判题方式的使用场景"""
print("\n=== 判题方式使用场景 ===")
scenarios = [
{
"名称": "字符串精确比较",
"适用": "输出结果固定的算法题",
"示例": "计算1+1的结果",
"验证方式": "InternalJudge(allowpe=False)"
},
{
"名称": "字符串容错比较",
"适用": "允许格式差异的题目",
"示例": "输出多个数字,允许不同的分隔符",
"验证方式": "InternalJudge(allowpe=True)"
},
{
"名称": "文件大小+MD5校验",
"适用": "二进制文件输出",
"示例": "图像处理、音频处理等",
"验证方式": "文件级别的校验"
},
{
"名称": "自定义验证程序",
"适用": "复杂的判题逻辑",
"示例": "浮点数比较、多解题目、交互题等",
"验证方式": "ExternalJudge"
}
]
for i, scenario in enumerate(scenarios, 1):
print(f"{i}. {scenario['名称']}")
print(f" 适用场景: {scenario['适用']}")
print(f" 典型示例: {scenario['示例']}")
print(f" 实现方式: {scenario['验证方式']}")
print()
def main():
"""主演示函数"""
print("BitOJ 判题系统验证程序演示")
print("=" * 50)
demo_internal_judge()
demo_custom_judge_config()
demo_judge_usage_scenarios()
print("演示完成!")
print("\n更多示例文件:")
print(" - float_validator.cpp: 浮点数比较验证程序")
print(" - multi_solution_validator.py: 多解验证程序")
print(" - StringFormatValidator.java: 格式验证程序")
print(" - range_validator.cpp: 数值范围验证程序")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,58 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
多解答案验证程序
适用于有多个正确答案的题目,如排序、排列等
使用: python multi_solution_validator.py input.txt expected.txt result.txt
"""
import sys
import re
def main():
if len(sys.argv) != 4:
print("WA")
return
try:
# 读取标准答案
with open(sys.argv[2], 'r') as f:
expected = f.read().strip()
# 读取用户输出
with open(sys.argv[3], 'r') as f:
result = f.read().strip()
# 去除多余的空白字符
expected = re.sub(r'\s+', ' ', expected)
result = re.sub(r'\s+', ' ', result)
# 解析数字
try:
expected_nums = list(map(int, expected.split()))
result_nums = list(map(int, result.split()))
except ValueError:
print("WA")
return
# 检查数量是否相同
if len(expected_nums) != len(result_nums):
print("WA")
return
# 检查是否包含相同的元素(允许不同的排列)
if sorted(expected_nums) != sorted(result_nums):
print("WA")
return
# 如果需要检查特定的排序顺序,可以添加额外的验证
# 这里我们接受任何包含相同元素的排列
print("AC")
except Exception:
print("WA")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,68 @@
// 数值范围验证程序
// 验证输出的数值是否在合理范围内
// 编译: g++ -o range_validator range_validator.cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
int main(int argc, char* argv[]) {
if (argc != 4) {
cout << "WA" << endl;
return 0;
}
ifstream input(argv[1]); // 输入数据,包含范围信息
ifstream expected(argv[2]); // 期望答案
ifstream result(argv[3]); // 用户输出
if (!input.is_open() || !expected.is_open() || !result.is_open()) {
cout << "WA" << endl;
return 0;
}
// 读取输入数据中的范围信息
int n;
input >> n;
vector<int> arr(n);
for (int i = 0; i < n; i++) {
input >> arr[i];
}
int min_val = *min_element(arr.begin(), arr.end());
int max_val = *max_element(arr.begin(), arr.end());
// 读取期望答案
int exp_result;
if (!(expected >> exp_result)) {
cout << "WA" << endl;
return 0;
}
// 读取用户答案
int user_result;
if (!(result >> user_result)) {
cout << "WA" << endl;
return 0;
}
// 验证答案是否在合理范围内
if (user_result < min_val || user_result > max_val) {
cout << "WA" << endl;
return 0;
}
// 验证答案是否正确
if (user_result == exp_result) {
cout << "AC" << endl;
} else {
cout << "WA" << endl;
}
input.close();
expected.close();
result.close();
return 0;
}

103
examples/test_validator.py Normal file
View File

@@ -0,0 +1,103 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
验证程序测试脚本
用于测试自定义验证程序是否工作正常
"""
import os
import subprocess
import tempfile
def test_float_validator():
"""测试浮点数验证程序"""
print("测试浮点数验证程序...")
# 创建测试文件
input_file = tempfile.NamedTemporaryFile(mode='w', delete=False)
input_file.write("1.0")
input_file.close()
expected_file = tempfile.NamedTemporaryFile(mode='w', delete=False)
expected_file.write("3.14159")
expected_file.close()
result_file = tempfile.NamedTemporaryFile(mode='w', delete=False)
result_file.write("3.14159001") # 轻微误差
result_file.close()
try:
# 编译验证程序
cmd = ['g++', '-o', 'float_validator', 'float_validator.cpp']
compile_result = subprocess.run(cmd, capture_output=True, text=True)
if compile_result.returncode != 0:
print("编译失败:", compile_result.stderr)
return
# 运行验证程序
cmd = ['./float_validator', input_file.name,
expected_file.name, result_file.name]
run_result = subprocess.run(cmd, capture_output=True, text=True)
print("验证结果:", run_result.stdout.strip())
# 清理
if os.path.exists('float_validator'):
os.remove('float_validator')
finally:
# 清理临时文件
for f in [input_file, expected_file, result_file]:
if os.path.exists(f.name):
os.unlink(f.name)
def test_multi_solution_validator():
"""测试多解验证程序"""
print("测试多解验证程序...")
# 创建测试文件
input_file = tempfile.NamedTemporaryFile(mode='w', delete=False)
input_file.write("")
input_file.close()
expected_file = tempfile.NamedTemporaryFile(mode='w', delete=False)
expected_file.write("1 2 3 4 5")
expected_file.close()
result_file = tempfile.NamedTemporaryFile(mode='w', delete=False)
result_file.write("5 4 3 2 1") # 相同元素,不同顺序
result_file.close()
try:
# 运行验证程序
cmd = ['python3', 'multi_solution_validator.py',
input_file.name, expected_file.name, result_file.name]
run_result = subprocess.run(cmd, capture_output=True, text=True)
print("验证结果:", run_result.stdout.strip())
finally:
# 清理临时文件
for f in [input_file, expected_file, result_file]:
if os.path.exists(f.name):
os.unlink(f.name)
def main():
"""主测试函数"""
print("=== 自定义验证程序测试 ===")
# 切换到示例目录
os.chdir('/Users/liushuming/Desktop/bitoj/examples')
test_float_validator()
print()
test_multi_solution_validator()
print("\n测试完成!")
if __name__ == "__main__":
main()