小学数学

news/2025/3/31 10:03:38/文章来源:https://www.cnblogs.com/gzslm123/p/18797340
这个作业属于哪个课程 作业课程
这个作业要求在哪里 作业要求
这个作业的目标 实现一个自动生成小学四则运算题目的命令行程序

成员:3123004217蔡宜桓
我的github:github仓库

一.PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 35 30
Estimate 估计这个任务需要多少时间 15 30
Development 开发 185 200
Analysis 需求分析 (包括学习新技术) 75 80
Design Spec 生成设计文档 25 20
Design Review 设计复审 35 30
Coding Standard 代码规范 (为目前的开发制定合适的规范) 30 25
Design 具体设计 35 40
Coding 具体编码 75 70
Code Review 代码复审 25 45
Test 测试(自我测试,修改代码,提交修改) 35 30
Reporting 报告 15 20
Test Repor 测试报告 25 15
Size Measurement 计算工作量 5 20
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 35 30
合计 650 685

二.代码展示

点击查看代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>#define MAX_QUESTIONS 10000
#define MAX_EXPR_LEN 100typedef struct {int numerator;int denominator;
} Fraction;typedef struct {char expression[MAX_EXPR_LEN];Fraction answer;
} Question;// 最大公约数
int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);
}// 约分分数
void simplify(Fraction *f) {int common = gcd(abs(f->numerator), abs(f->denominator));f->numerator /= common;f->denominator /= common;if (f->denominator < 0) {f->numerator *= -1;f->denominator *= -1;}
}// 生成随机分数
Fraction random_fraction(int range) {Fraction f;f.denominator = rand() % (range - 1) + 2; // 分母至少为2f.numerator = rand() % (f.denominator * (range - 1)) + 1;simplify(&f);return f;
}// 生成随机自然数或分数
Fraction random_number(int range, bool allow_fraction) {if (allow_fraction && rand() % 4 == 0) { // 25%概率生成分数return random_fraction(range);} else {Fraction f;f.numerator = rand() % range;f.denominator = 1;return f;}
}// 分数转字符串
void fraction_to_str(Fraction f, char *str) {if (f.denominator == 1) {sprintf(str, "%d", f.numerator);} else if (abs(f.numerator) > f.denominator) {int whole = f.numerator / f.denominator;int remainder = abs(f.numerator) % f.denominator;sprintf(str, "%d'%d/%d", whole, remainder, f.denominator);} else {sprintf(str, "%d/%d", f.numerator, f.denominator);}
}// 字符串转分数
Fraction str_to_fraction(const char *str) {Fraction f;int whole = 0, numerator = 0, denominator = 1;if (strchr(str, '\'') != NULL) {sscanf(str, "%d'%d/%d", &whole, &numerator, &denominator);f.numerator = whole * denominator + (whole >= 0 ? numerator : -numerator);f.denominator = denominator;} else if (strchr(str, '/') != NULL) {sscanf(str, "%d/%d", &numerator, &denominator);f.numerator = numerator;f.denominator = denominator;} else {sscanf(str, "%d", &numerator);f.numerator = numerator;f.denominator = 1;}simplify(&f);return f;
}// 分数加法
Fraction add(Fraction a, Fraction b) {Fraction result;result.numerator = a.numerator * b.denominator + b.numerator * a.denominator;result.denominator = a.denominator * b.denominator;simplify(&result);return result;
}// 分数减法
Fraction subtract(Fraction a, Fraction b) {Fraction result;result.numerator = a.numerator * b.denominator - b.numerator * a.denominator;result.denominator = a.denominator * b.denominator;simplify(&result);return result;
}// 分数乘法
Fraction multiply(Fraction a, Fraction b) {Fraction result;result.numerator = a.numerator * b.numerator;result.denominator = a.denominator * b.denominator;simplify(&result);return result;
}// 分数除法
Fraction divide(Fraction a, Fraction b) {Fraction result;result.numerator = a.numerator * b.denominator;result.denominator = a.denominator * b.numerator;simplify(&result);return result;
}// 生成表达式和答案
void generate_expression(Question *q, int range, int operators_left, bool in_parentheses) {if (operators_left == 0) {Fraction num = random_number(range, true);char num_str[20];fraction_to_str(num, num_str);strcat(q->expression, num_str);q->answer = num;return;}bool use_parentheses = in_parentheses ? false : (rand() % 2 == 0 && operators_left > 1);if (use_parentheses) {strcat(q->expression, "(");}// 左子表达式int left_operators = rand() % operators_left;if (left_operators == operators_left) left_operators--;generate_expression(q, range, left_operators, use_parentheses);// 运算符char op;Fraction temp_answer;switch (rand() % 4) {case 0: op = '+'; break;case 1: op = '-'; break;case 2: op = '*'; break;case 3: op = '/'; break;}// 处理减法和除法的限制bool valid = false;Fraction right_num;char right_str[20];int attempts = 0;do {attempts++;if (attempts > 10) { // 避免无限循环op = (op == '-' || op == '/') ? '+' : op;}// 生成右子表达式char temp_expr[MAX_EXPR_LEN] = "";Question temp_q;strcpy(temp_q.expression, temp_expr);generate_expression(&temp_q, range, operators_left - left_operators - 1, use_parentheses);right_num = temp_q.answer;strcpy(right_str, temp_q.expression);if (op == '-') {valid = (q->answer.numerator * right_num.denominator >= right_num.numerator * q->answer.denominator);} else if (op == '/') {valid = (right_num.numerator != 0);} else {valid = true;}} while (!valid);// 添加运算符和右子表达式char op_with_spaces[4] = " ";op_with_spaces[1] = op;op_with_spaces[2] = ' ';strcat(q->expression, op_with_spaces);strcat(q->expression, right_str);// 计算答案switch (op) {case '+': q->answer = add(q->answer, right_num); break;case '-': q->answer = subtract(q->answer, right_num); break;case '*': q->answer = multiply(q->answer, right_num); break;case '/': q->answer = divide(q->answer, right_num); break;}if (use_parentheses) {strcat(q->expression, ")");}
}// 检查题目是否重复
bool is_duplicate(Question *questions, int count, Question *new_q) {// 简化检查:比较答案和表达式长度for (int i = 0; i < count; i++) {if (questions[i].answer.numerator == new_q->answer.numerator &&questions[i].answer.denominator == new_q->answer.denominator &&strlen(questions[i].expression) == strlen(new_q->expression)) {// 更复杂的检查可以在这里添加return true;}}return false;
}// 生成题目
void generate_questions(int count, int range, const char *exercise_file, const char *answer_file) {Question questions[MAX_QUESTIONS];FILE *ef = fopen(exercise_file, "w");FILE *af = fopen(answer_file, "w");if (!ef || !af) {printf("无法打开输出文件\n");return;}srand(time(NULL));for (int i = 0; i < count; i++) {Question q;strcpy(q.expression, "");int operators = rand() % 3 + 1; // 1-3个运算符generate_expression(&q, range, operators, false);// 确保不重复while (is_duplicate(questions, i, &q)) {strcpy(q.expression, "");generate_expression(&q, range, operators, false);}questions[i] = q;// 写入题目文件fprintf(ef, "%d. %s =\n", i + 1, q.expression);// 写入答案文件char answer_str[20];fraction_to_str(q.answer, answer_str);fprintf(af, "%d. %s\n", i + 1, answer_str);}fclose(ef);fclose(af);
}// 检查答案
void check_answers(const char *exercise_file, const char *answer_file, const char *grade_file) {FILE *ef = fopen(exercise_file, "r");FILE *af = fopen(answer_file, "r");FILE *gf = fopen(grade_file, "w");if (!ef || !af || !gf) {printf("无法打开输入/输出文件\n");return;}int correct_count = 0, wrong_count = 0;int correct_indices[MAX_QUESTIONS], wrong_indices[MAX_QUESTIONS];char line[256];int index;while (fgets(line, sizeof(line), ef)) {sscanf(line, "%d.", &index);char answer_line[256];fgets(answer_line, sizeof(answer_line), af);// 提取正确答案char correct_answer[20];sscanf(answer_line, "%*d. %s", correct_answer);Fraction correct = str_to_fraction(correct_answer);// 提取用户答案char *eq_pos = strchr(line, '=');if (!eq_pos || *(eq_pos + 1) == '\n') {// 没有答案wrong_indices[wrong_count++] = index;continue;}char user_answer[20];sscanf(eq_pos + 1, "%s", user_answer);Fraction user = str_to_fraction(user_answer);if (user.numerator == correct.numerator && user.denominator == correct.denominator) {correct_indices[correct_count++] = index;} else {wrong_indices[wrong_count++] = index;}}// 写入成绩文件fprintf(gf, "Correct: %d (", correct_count);for (int i = 0; i < correct_count; i++) {fprintf(gf, "%d", correct_indices[i]);if (i < correct_count - 1) fprintf(gf, ", ");}fprintf(gf, ")\n");fprintf(gf, "Wrong: %d (", wrong_count);for (int i = 0; i < wrong_count; i++) {fprintf(gf, "%d", wrong_indices[i]);if (i < wrong_count - 1) fprintf(gf, ", ");}fprintf(gf, ")\n");fclose(ef);fclose(af);fclose(gf);
}// 打印帮助信息
void print_help() {printf("使用方法:\n");printf("生成题目: program -n <题目数量> -r <数值范围>\n");printf("检查答案: program -e <题目文件> -a <答案文件>\n");
}int main(int argc, char *argv[]) {if (argc < 2) {print_help();return 1;}if (strcmp(argv[1], "-n") == 0 && argc >= 5 && strcmp(argv[3], "-r") == 0) {int count = atoi(argv[2]);int range = atoi(argv[4]);if (count <= 0 || range <= 0) {printf("无效的参数值\n");return 1;}generate_questions(count, range, "Exercises.txt", "Answers.txt");printf("已生成 %d 道题目,范围在 %d 以内\n", count, range);} else if (strcmp(argv[1], "-e") == 0 && argc >= 5 && strcmp(argv[3], "-a") == 0) {check_answers(argv[2], argv[4], "Grade.txt");printf("已检查答案,结果保存在 Grade.txt\n");} else {print_help();return 1;}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/906992.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VMware Workstation不支持的硬件版本,模块Upgrade启动失败

1、我是从高版本的VMware Workstation降级后,再打开之前的虚拟机报错如下 2、打开虚拟机文件目录,用文本打开虚拟机的 .vmx文件,搜索定位到 virtualHW 字段,修改该字段为自己当前VMware版本,然后保存并开机

Next.js中间件权限绕过漏洞分析(CVE-2025-29927)

本文代码版本为next.js-15.2.2 本篇文章首发在先知社区:https://xz.aliyun.com/news/17403 一、漏洞概述 CVE-2025-29927是Next.js框架中存在的一个高危中间件逻辑绕过漏洞,允许攻击者通过构造特定HTTP请求头,绕过中间件的安全控制逻辑(如身份验证、路径重写、CSP防护等)。…

vue+openlayers示例:线水流效果(附源码下载)

demo源码运行环境以及配置运行环境:依赖Node安装环境,demo本地Node版本:推荐v16+。 运行工具:vscode或者其他工具。 配置方式:下载demo源码,vscode打开,然后顺序执行以下命令: (1)下载demo环境依赖包命令:npm i (2)启动demo命令:npm run dev (3)打包demo命令: …

蓝屏STOP:0x0000007B

生产线需要,得准备一台Windows XP的操作系统电脑。在安装时,出现下面蓝屏,A problem has been detected and windows has been shut down to prevent damage to your computer. If this is the first time youve seen this stop error screen, restart your computer. If th…

必看!2025 年颠覆测试行业的 10 大 AI 自动化测试工具/平台(上篇)

大家好,我是狂师。 上周小孩子生病,住院照顾,停更了几天。 各位看官,等着急了吧,之前有粉丝后台留言,想了解学习一下,AI这么火爆,那市面上AI与自动化测试结合起来的有哪些推荐的工具/平台。 今天就这个话题来聊一聊。 前言 在软件迭代以“天”为单位的今天,随着软件迭…

2025年企业必读指南:文件摆渡系统的5大核心功能

在数字化转型的浪潮中,企业面临着前所未有的挑战与机遇。优化信息流转、提升协作效率、确保数据安全及合规性,已成为企业持续发展的关键要素。在这一背景下,文件摆渡系统作为连接不同网络、网域之间的桥梁,承担着文件传输、共享、管理和归档等多重任务,其重要性日益凸显。…

利用AI增强VS Code TypeScript插件:AnyToTS带来编程新体验

Any to TS: VSCode 扩展插件 概述 "Any to TS" 是一个强大的 VSCode 扩展插件,旨在将任何对象转换为 TypeScript 类型或接口。该工具基于 vscode-json-to-ts 进行功能扩展,提供了一系列便捷的功能,帮助开发者更高效地处理 TypeScript 类型定义。 核心功能 传统功能…

虚函数表里有什么?(一)——从一个普通类开始

本系列文章,旨在探究C++虚函数表中除函数地址以外的条目,以及这些条目的设计意图和作用,并介绍与此相关的C++类对象内存布局,最后将两者用图解的形式结合起来,给读者带来全局性的视角。让我们从一个简单的类出发,开启我们的探索之旅。前言 本系列文章,旨在探究C++虚函数…

《HelloGitHub》第 108 期

兴趣是最好的老师,HelloGitHub 让你对开源感兴趣!简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。github.com/521xueweihan/HelloGitHub这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等,涵盖多种编程语言 Python、Java、Go、C/C++、Swift...让你在短…

读DAMA数据管理知识体系指南33参考数据和主数据活动

读DAMA数据管理知识体系指南33参考数据和主数据活动1. 主数据管理活动 1.1. 识别驱动因素和需求1.1.1. 每个组织都有不同的主数据管理驱动因素和障碍,受系统的数量和类型、使用年限、支持的业务流程以及交易和分析中数据使用方式的影响1.2. 评估和评价数据源1.2.1. 现有应用中…

C++内存序

C++的3种memory model: + sequentially consistent + relexed + acquire-release 对应5.3章《C++ concurrency in action》5.3 Synchronizing operations and enforcing ordering 首先就是对于程序来说都是通过 "happens-before" 和 "synchronizes-with" …

如何快速解决单细胞拟时序分析旧版本Monocle包导致的orderCells过程的报错

当我们整理好一版本的单细胞转录组数据分析代码,并完成一个项目的单细胞转录组数据分析项目。当我们再进行另外一个单细胞转录组数据的项目分析时,突然发现原来跑通的代谢,突然一直报错那是一件很苦恼的问题,想必各位科研党遇到这种问题是不是也有砸电脑的心情。今天主要写…