结对编程

结对编程两个人学号:
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. 角色分工经验

    • 学生1:专注核心算法实现(题目生成、括号逻辑)
    • 学生2:负责最大数值、除零处理
  2. 开发难点突破

    • 括号嵌套与字符串拼接的协调
    • 递归生成时的栈溢出风险控制
    • 用户输入异常处理(缓冲区溢出防护)
  3. 合作收获

    • 防御式编程思维的培养
    • 结对轮换模式提升代码可维护性
    • 高效沟通
    • 优势互补

五、编程代码

#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;
}

posted on 2025-04-17 11:25  张诗昊  阅读(50)  评论(0)    收藏  举报

导航