3.1 实战·开发题目数据生成器

在实际编程题目的测评场景中,通常需要多组独立的测试数据文件(如test1.in`test10.in`)和对应的答案文件(`test1.out`test10.out)。本节将基于之前的项目,修改gen.py使其调用std.py的功能,一次性生成10组独立的输入输出文件,提升工具的实用性。

一、实现思路

实现思路

  • gen.py中循环生成10组数据,每组数据单独保存为testN.in(N为1~10)。
  • 通过import语句导入std.py中的calculate_answerssave_answers函数,直接利用其计算和保存答案的功能,避免代码重复。
  • 确保文件名的规范性(如test1.in对应test1.out),方便后续check.py批量检测。
二、gen.py:调用std.py生成多组文件
1. gen.py代码
# gen.py
import random
# 导入std.py中的函数(需保证std.py与gen.py在同一目录)
from std import calculate_answers, save_answers

def generate_single_test_case(min_val=-1000, max_val=1000):
    """生成单组测试数据(a, b)"""
    a = random.randint(min_val, max_val)
    b = random.randint(min_val, max_val)
    return (a, b)

def save_single_test_case(data, case_num):
    """保存单组测试数据到testN.in"""
    filename = f"test{case_num}.in"  # 文件名格式:test1.in, test2.in...
    with open(filename, "w", encoding="utf-8") as f:
        f.write(f"{data[0]} {data[1]}\n")  # 写入a和b
    return filename

def generate_multiple_cases(total_cases=10):
    """生成多组测试数据及对应的答案文件"""
    for case_num in range(1, total_cases + 1):
        # 1. 生成单组输入数据
        test_case = generate_single_test_case()
        # 2. 保存输入文件(testN.in)
        input_file = save_single_test_case(test_case, case_num)
        # 3. 调用std.py的函数计算答案并保存到testN.out
        # 注意:calculate_answers需要接收列表形式的输入,这里用[test_case]包装
        answers = calculate_answers([test_case])
        output_file = f"test{case_num}.out"
        save_answers(answers, output_file)
        print(f"生成第{case_num}组:{input_file}{output_file}")

if __name__ == "__main__":
    generate_multiple_cases(total_cases=10)
    print("所有测试数据及答案文件生成完成")
2. 代码解析
  • 函数拆分:将原generate_test_data拆分为generate_single_test_case(生成单组数据)和generate_multiple_cases(循环生成多组),逻辑更清晰。
  • 导入复用:通过from std import ...导入calculate_answerssave_answers,直接使用std.py的计算逻辑,确保输入输出的一致性(避免重复编写求和代码导致的错误)。
  • 文件名格式化:使用f-字符串f"test{case_num}.in"生成文件名,保证每组输入输出文件一一对应(如test3.in对应test3.out)。
  • 批量生成:通过for case_num in range(1, 11)循环生成10组数据,支持通过total_cases参数调整数量(如生成20组)。
三、验证std.py的兼容性

由于gen.py导入了std.py的函数,需确保std.py的代码无需修改即可正常工作。之前编写的std.py中,calculate_answers接收的是列表形式的(a, b)元组(如[(35, 72), (-12, 49)]),而gen.py中通过[test_case](如[(35, 72)])包装单组数据,完全符合其参数要求,因此无需修改std.py

std.py的核心代码回顾:

# std.py
def calculate_answers(test_data):
    """计算每组数据的答案(a + b),返回答案列表"""
    answers = []
    for a, b in test_data:
        answers.append(a + b)
    return answers

def save_answers(answers, filename="std_ans.txt"):
    """将标准答案写入文件,每行一个结果"""
    with open(filename, "w", encoding="utf-8") as f:
        for ans in answers:
            f.write(f"{ans}\n")
四、运行效果与文件结构

执行修改后的gen.py,终端会输出:

生成第1组:test1.in 和 test1.out
生成第2组:test2.in 和 test2.out
...
生成第10组:test10.in 和 test10.out
所有测试数据及答案文件生成完成

此时目录下会生成20个文件:

  • 输入文件:test1.in~test10.in,每个文件含一行数据(如test1.in内容为35 72)。
  • 输出文件:test1.out~test10.out,每个文件含一行答案(如test1.out内容为107)。
六、项目优势与应用场景
  1. 自动化程度高:通过gen.py一次运行即可生成全套测试数据和答案,无需手动调用std.py10次。
  2. 代码复用性强:复用std.py的核心函数,避免重复开发,减少逻辑不一致的风险。
  3. 符合测评规范:生成的testN.intestN.out格式符合编程竞赛、在线测评系统(OJ)的常见要求,便于直接用于教学或测评。

通过这次拓展,你掌握了模块间函数调用的技巧,以及批量处理文件的方法。这种思路可以直接应用到“密码管理器”(批量生成加密文件)和“活动管理系统”(批量导出报名信息)等项目中。下一节,我们将学习如何通过命令行参数进一步提升工具的灵活性(如允许用户指定生成数据的范围和数量)。现在,试着运行修改后的gen.py,然后手动检查test1.intest1.out是否匹配吧!

七、写在最后

若需要更改题目,可以直接在gen.py中修改判断数据成立的条件,在std.py中修改输出的代码,无需手动调整数据,这也太方便了!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐