实现小学老师每周给同学出300道四则运算练习题的程序
这是2352625同学和2313123同学实现的小学老师每周给同学出300道四则运算练习题的程序
一、算法设计思路
1.初始化与输入
随机数种子:利用 srand(time(0)) 初始化随机数生成器,确保每次运行程序生成的题目 不同。
运算符输入:提示用户输入要使用的运算符(如 +-*/),存储在 operatorInput 字符串中。
答案小数设置:询问用户答案是否允许为小数,根据用户输入(y 或 n)设置 allowDecimal 布尔变量。
题目小数位数设置:提示用户输入题目中出现的小数位数,存储在 decimalPlaces 变量中。若输入 0,则表示题目中只出现整数。
2.题目生成
随机数生成函数:generateRandomNumber 函数根据 decimalPlaces 生成指定小数位数的随机数。如果 decimalPlaces 为 0,生成 0 到 100 的整数;否则,通过将随机数扩大 10 的 decimalPlaces 次方倍,再除以该倍数来得到指定小数位数的随机数。
循环生成题目:通过一个 while 循环生成 300 道题目。在每次循环中,生成三个随机数 num1、num2、num3,并从用户输入的运算符中随机选择两个运算符 op1 和 op2。
计算与筛选题目:调用 calculate 函数计算表达式 num1 op1 num2 op2 num3 的值。calculate 函数根据不同的运算符组合进行计算,并处理除零错误。若计算结果在 0 到 1000 之间,则将该题目存储到 exercises 向量中,同时将答案存储到 answers 向量中。
3.题目检索
输入处理:提示用户输入要检索的题号,支持在题号后加 = 来显示答案。将用户输入存储在 queryInput 字符串中。
解析输入:检查 queryInput 中是否包含 = 符号。若包含,提取题号部分并将 showAnswer 设为 true;否则,直接提取题号。
检索与输出:根据题号在 exercises 向量中查找对应的题目。若找到,去除题目字符串中的题号部分。如果 showAnswer 为 true,则从 answers 向量中获取答案并一起输出;否则,仅输出题目。若题号无效,则提示用户未找到对应题目。
二、程序代码
点击查看代码
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <string>
#include <iomanip>
#include <sstream>
#include <algorithm>
using namespace std;
double calculate(double num1, double num2, double num3, char op1, char op2, bool allowDecimal) {
double result;
if (op1 == '+') {
if (op2 == '+') {
result = num1 + num2 + num3;
} else if (op2 == '-') {
result = num1 + num2 - num3;
} else if (op2 == '*') {
result = num1 + num2 * num3;
} else if (op2 == '/') {
if (num3 != 0) {
result = num1 + num2 / num3;
} else {
return -1;
}
}
} else if (op1 == '-') {
if (op2 == '+') {
result = num1 - num2 + num3;
} else if (op2 == '-') {
result = num1 - num2 - num3;
} else if (op2 == '*') {
result = num1 - num2 * num3;
} else if (op2 == '/') {
if (num3 != 0) {
result = num1 - num2 / num3;
} else {
return -1;
}
}
} else if (op1 == '*') {
if (op2 == '+') {
result = num1 * num2 + num3;
} else if (op2 == '-') {
result = num1 * num2 - num3;
} else if (op2 == '*') {
result = num1 * num2 * num3;
} else if (op2 == '/') {
if (num3 != 0) {
result = num1 * num2 / num3;
} else {
return -1;
}
}
} else if (op1 == '/') {
if (num2 != 0) {
if (op2 == '+') {
result = num1 / num2 + num3;
} else if (op2 == '-') {
result = num1 / num2 - num3;
} else if (op2 == '*') {
result = num1 / num2 * num3;
} else if (op2 == '/') {
if (num3 != 0) {
result = num1 / num2 / num3;
} else {
return -1;
}
}
} else {
return -1;
}
}
if (!allowDecimal && static_cast<int>(result) != result) {
return -1;
}
return result;
}
double generateRandomNumber(int decimalPlaces, int max = 100) {
int multiplier = 1;
for (int i = 0; i < decimalPlaces; ++i) {
multiplier *= 10;
}
return static_cast<double>(rand() % (max * multiplier)) / multiplier;
}
string removeTrailingZeros(const string& str) {
string result = str;
auto dotPos = result.find('.');
if (dotPos != string::npos) {
auto it = result.rbegin();
while (it != result.rend() && *it == '0') {
++it;
}
if (*it == '.') {
++it;
}
result.erase(it.base(), result.end());
}
return result;
}
string numToString(double num, int decimalPlaces) {
ostringstream oss;
oss << fixed << setprecision(decimalPlaces) << num;
return removeTrailingZeros(oss.str());
}
int main() {
srand(time(0));
vector<string> exercises;
vector<double> answers;
int count = 0;
string operatorInput;
cout << "请输入要使用的运算符(例如 +-*/ ): ";
cin >> operatorInput;
bool allowDecimal;
char decimalChoice;
cout << "答案是否允许为小数? (y/n): ";
cin >> decimalChoice;
allowDecimal = (decimalChoice == 'y' || decimalChoice == 'Y');
int decimalPlaces;
cout << "请输入题目中出现的小数位数(输入 0 表示只出现整数): ";
cin >> decimalPlaces;
while (count < 300) {
double num1 = generateRandomNumber(decimalPlaces);
double num2 = generateRandomNumber(decimalPlaces);
double num3 = generateRandomNumber(decimalPlaces);
char op1 = operatorInput[rand() % operatorInput.length()];
char op2 = operatorInput[rand() % operatorInput.length()];
double result = calculate(num1, num2, num3, op1, op2, allowDecimal);
if (result >= 0 && result <= 1000) {
string exercise = to_string(count + 1) + ". " +
numToString(num1, decimalPlaces) + " " + op1 + " " +
numToString(num2, decimalPlaces) + " " + op2 + " " +
numToString(num3, decimalPlaces);
exercises.push_back(exercise);
answers.push_back(result);
cout << exercise << endl;
count++;
}
}
string queryInput;
cout << "请输入要检索的题号(输入 0 退出,题号后加 '=' 显示答案): ";
while (cin >> queryInput && queryInput != "0") {
size_t equalPos = queryInput.find('=');
int queryNumber;
bool showAnswer = false;
if (equalPos != string::npos) {
string numberPart = queryInput.substr(0, equalPos);
queryNumber = stoi(numberPart);
showAnswer = true;
} else {
queryNumber = stoi(queryInput);
}
if (queryNumber >= 1 && queryNumber <= exercises.size()) {
string exercise = exercises[queryNumber - 1];
auto pos = exercise.find('.');
if (pos != string::npos) {
exercise = exercise.substr(pos + 2);
}
if (showAnswer) {
cout << "第" << queryNumber << "道题目及答案为: " << exercise;
double answer = answers[queryNumber - 1];
cout << " = " << numToString(answer, decimalPlaces);
} else {
cout << "第" << queryNumber << "道题目为: " << exercise;
}
cout << endl;
} else {
cout << "未找到该题号对应的题目。" << endl;
}
cout << "请输入要检索的题号(输入 0 退出,题号后加 '=' 显示答案): ";
}
return 0;
}
三、运算结果
1.初始化与输入

2.题目生成

3.题目检索

四、结对编程作业体会
1.优势
知识互补:在本次作业中,我和搭档在编程知识和技能方面各有所长。我对算法逻辑的设计较为熟悉,而搭档在代码实现和细节处理上更加细致。例如,在实现 calculate 函数时,我提出了整体的运算逻辑框架,搭档则补充了各种边界情况的处理,如除零错误的检查,使函数更加健壮。
提高效率:两人同时工作可以加快开发进度。在生成题目部分,我们分工协作,一人负责编写随机数生成和运算符选择的代码,另一人负责计算表达式和筛选题目。通过并行工作,原本可能需要较长时间完成的任务在较短时间内就得以实现。
增强代码质量:结对编程过程中的相互审查和讨论大大提高了代码质量。在编写去除小数末尾 0 的 removeTrailingZeros 函数时,我们对字符串处理的逻辑进行了多次讨论,优化了代码的可读性和执行效率。同时,在代码风格上也达成了一致,使整个程序的代码风格统一、规范。
2.挑战
沟通成本:在合作过程中,沟通是关键,但也可能带来一定成本。有时我们对问题的理解和解决方案的思路存在差异,需要花费时间进行讨论和协调。例如,在设计题目检索功能时,对于如何处理用户输入的格式,我们最初有不同的想法,经过充分沟通和利弊分析,才确定了最终方案。
工作节奏差异:我和搭档的工作节奏有所不同。我习惯快速搭建框架,然后逐步完善细节;而搭档更倾向于从一开始就注重细节,确保每一行代码都准确无误。这在合作初期导致了一些进度上的不一致,需要我们相互适应和调整,找到一个双方都能接受的工作节奏。

浙公网安备 33010602011771号