结对编程
结对编程两个人学号:
2352902
2352907
一、算法设计思路
1. 核心架构设计
- 用户交互模块:通过控制台实现参数设置
- 题目生成模块:递归生成算法
- 括号处理模块:随机插入括号策略
- 查重机制:字符串比对查重
- 答案验证模块:即时计算验证
- 文件处理模块:题目持久化存储
2. 关键算法流程图
graph TD
A[开始] --> B[参数输入]
B --> C{参数合法?}
C -->|是| D[生成题目]
C -->|否| E[使用默认值]
D --> F{查重通过?}
F -->|是| G[计算结果]
F -->|否| D
G --> H{答案有效?}
H -->|是| I[存储题目]
H -->|否| D
I --> J{完成数量?}
J -->|否| D
J -->|是| K[输出文件]
二、程序代码说明
1. 核心函数说明表
| 函数名 | 功能描述 | 输入参数 | 返回值 |
|---|---|---|---|
checkAnswer |
答案范围验证 | 计算结果 | 布尔值 |
isDuplicate |
题目重复检测 | 题目字符串 | 布尔值 |
calculateResult |
表达式求值 | 题目字符串 | 计算结果 |
generateQuestion |
题目生成主逻辑 | 结果指针/难度/运算数/运算符 | void |
2. 关键代码段解析
// 带括号的题目生成逻辑
if (hasBracket) {
int bracketStart = rand() % (numOperands - 1);
int bracketEnd = rand() % (numOperands - 1);
// 括号位置校正逻辑
if (bracketStart > bracketEnd) {
int temp = bracketStart;
bracketStart = bracketEnd;
bracketEnd = temp;
}
// 括号插入实现
for (i = 0; i < numOperands; i++) {
if (i == bracketStart) sprintf(question + index, "(");
// 数值和运算符拼接
if (i == bracketEnd) sprintf(question + index, ")");
}
}
三、运行结果示例
1.控制台交互过程

2. 输出文件示例

四、结对编程体会
学号2352902与学号2352907合作体会:
-
角色分工经验
- 学生1:专注核心算法实现(题目生成、括号逻辑)
- 学生2:负责最大数值、除零处理
-
开发难点突破
- 括号嵌套与字符串拼接的协调
- 递归生成时的栈溢出风险控制
- 用户输入异常处理(缓冲区溢出防护)
-
合作收获
- 防御式编程思维的培养
- 结对轮换模式提升代码可维护性
- 高效沟通
- 优势互补
五、编程代码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define MAX_QUESTIONS 10 // 一次生成题目数量
#define MAX_DIFFICULTY 100 // 最大难度值,对应数字范围等难度指标
#define MAX_QUESTION_LENGTH 100 // 题目字符串最大长度
#define MAX_OPERANDS 5 // 最多运算数个数
// 存储已生成题目,用于去重
char generatedQuestions[MAX_QUESTIONS][MAX_QUESTION_LENGTH];
int questionCount = 0;
// 检查答案是否在0 - 1000之间
int checkAnswer(int result) {
return result >= 0 && result <= 1000;
}
// 检查题目是否重复
int isDuplicate(char *question) {
for (int i = 0; i < questionCount; i++) {
if (strcmp(generatedQuestions[i], question) == 0) {
return 1;
}
}
return 0;
}
// 计算题目结果
int calculateResult(char *question) {
int result = 0;
int num[MAX_OPERANDS];
char op[MAX_OPERANDS - 1];
int numIndex = 0, opIndex = 0;
int i = 0;
while (question[i] != '\0') {
if (question[i] >= '0' && question[i] <= '9') {
int temp = 0;
while (question[i] >= '0' && question[i] <= '9') {
temp = temp * 10 + (question[i] - '0');
i++;
}
num[numIndex++] = temp;
i--;
} else if (question[i] == '+' || question[i] == '-' || question[i] == '*' || question[i] == '/') {
op[opIndex++] = question[i];
}
i++;
}
result = num[0];
for (i = 0; i < opIndex; i++) {
switch (op[i]) {
case '+':
result += num[i + 1];
break;
case '-':
result -= num[i + 1];
break;
case '*':
result *= num[i + 1];
break;
case '/':
if (num[i + 1] != 0) {
result /= num[i + 1];
} else {
return -1; // 除数为0返回错误值
}
break;
}
}
return result;
}
// 生成单个四则运算题目并计算结果
void generateQuestion(int *result, int difficulty, int numOperands, char *selectedOps) {
int nums[MAX_OPERANDS];
char operators[MAX_OPERANDS - 1];
char question[MAX_QUESTION_LENGTH];
int i;
// 生成运算数
for (i = 0; i < numOperands; i++) {
nums[i] = rand() % (difficulty + 1);
}
// 生成运算符
int opCount = strlen(selectedOps);
for (i = 0; i < numOperands - 1; i++) {
operators[i] = selectedOps[rand() % opCount];
}
// 尝试添加括号
int hasBracket = rand() % 2;
if (hasBracket) {
int bracketStart = rand() % (numOperands - 1);
int bracketEnd = rand() % (numOperands - 1);
if (bracketStart > bracketEnd) {
int temp = bracketStart;
bracketStart = bracketEnd;
bracketEnd = temp;
}
int index = 0;
for (i = 0; i < numOperands; i++) {
if (i == bracketStart) {
sprintf(question + index, "(");
index += 1;
}
sprintf(question + index, "%d", nums[i]);
index += strlen(question + index);
if (i < numOperands - 1) {
sprintf(question + index, " %c ", operators[i]);
index += strlen(question + index);
}
if (i == bracketEnd) {
sprintf(question + index, ")");
index += 1;
}
}
} else {
int index = 0;
for (i = 0; i < numOperands; i++) {
sprintf(question + index, "%d", nums[i]);
index += strlen(question + index);
if (i < numOperands - 1) {
sprintf(question + index, " %c ", operators[i]);
index += strlen(question + index);
}
}
}
question[strlen(question)] = '\0';
if (isDuplicate(question)) {
generateQuestion(result, difficulty, numOperands, selectedOps);
return;
}
strcpy(generatedQuestions[questionCount], question);
questionCount++;
*result = calculateResult(question);
if (!checkAnswer(*result)) {
generateQuestion(result, difficulty, numOperands, selectedOps);
return;
}
printf("%s\n", question);
}
int main() {
srand((unsigned int)time(NULL));
int i, result, difficulty, numOperands;
FILE *fp;
char selectedOps[5]; // 存储用户选择的运算符
// 让用户选择参与运算的运算符
printf("请选择参与运算的运算符(例如输入+ - *表示加减乘,留空则默认加减乘除):");
fgets(selectedOps, sizeof(selectedOps), stdin);
selectedOps[strcspn(selectedOps, "\n")] = '\0'; // 去除换行符
if (strlen(selectedOps) == 0) {
strcpy(selectedOps, "+-*/");
}
// 让用户输入难度值
printf("请输入难度值(1 - %d):", MAX_DIFFICULTY);
scanf("%d", &difficulty);
if (difficulty < 1 || difficulty > MAX_DIFFICULTY) {
difficulty = 50; // 默认难度
printf("难度值输入有误,使用默认难度值50\n");
}
// 让用户输入运算数个数
printf("请输入运算数个数(2 - %d):", MAX_OPERANDS);
scanf("%d", &numOperands);
if (numOperands < 2 || numOperands > MAX_OPERANDS) {
numOperands = 3; // 默认运算数个数
printf("运算数个数输入有误,使用默认值3\n");
}
// 打开文件用于存储题目
fp = fopen("math_questions.txt", "w");
if (fp == NULL) {
perror("Failed to open file");
return 1;
}
printf("生成的%d道四则运算题目如下:\n", MAX_QUESTIONS);
for (i = 0; i < MAX_QUESTIONS; i++) {
generateQuestion(&result, difficulty, numOperands, selectedOps);
fprintf(fp, "%s\n", generatedQuestions[i]);
}
fclose(fp);
// 提供查看答案功能
char viewAnswer;
printf("是否查看答案?(y/n):");
scanf(" %c", &viewAnswer);
if (viewAnswer == 'y' || viewAnswer == 'Y') {
fp = fopen("math_questions.txt", "r");
if (fp != NULL) {
char line[MAX_QUESTION_LENGTH];
while (fgets(line, sizeof(line), fp) != NULL) {
line[strcspn(line, "\n")] = '\0'; // 去除换行符
int answer = calculateResult(line);
printf("%s = %d\n", line, answer);
}
fclose(fp);
} else {
perror("Failed to open file for viewing answers");
}
}
return 0;
}
浙公网安备 33010602011771号