结对项目:四则运算题目生成--第一阶段

1、第一阶段要求

写一个能自动生成小学四则运算的命令行“软件”,分别满足下面的各种需求。

下面这些需求都可以用命令行参数的形式来指定:

a)一次可以出一千道题目,并且没有重复的,把题目写入一个文件中。

b)逐步扩展功能和可以支持的表达式类型,最后可以支持最多10个运算符,括号数量不限制的表达式。

c)出了整数以外,还要支持真分数的四则运算。(例如:1/6+1/8=7/24)

d)让程序能接受用户输入答案,并判定对错,最后给出总共 对/错 的数量。

 

2、解题思路 

    题目要求一次可以出一千道题目,所以考虑运用随机数生成操作数和操作码,然后以文件流的形式输出写入文件,允许输入小于1000的数值来控制输出题数;在进行真分数的四则运算时,先转换为浮点数的运算,然后再将结果转换为分数:当用户通过运算输入答案后,程序判断对错,此时需要对四则运算表达式进行求值,可利用以前学过的栈的相关知识;因为程序要实现多个功能,所以用输入不同的不同的数字来控制执行不同功能。

 

3、程序设计实现过程

(1)、 生成题目时,通过输入num的值来控制执行生成函数的次数,生成对应数目的题目,生成函数中用随机数rand()生成表达式长度和操作数以及操作符,然后将生成的题目保存到question.txt文件中;

(2)、运用栈来进行表达式求值:

    以表达式“7+(5-1)*3+9/2”为例,首先将中缀表达式转化为后缀表达式,转化规则为:从左到右遍历中缀表达式的每一数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈  顶符号的优先级,是右括号或优先级低于栈顶符号(乘除优先加减)则栈顶元素依次出栈并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。

    示例步骤:

       a.初始化一空栈,用来对符号进出栈使用。

 

       b.第一个字符是数字7,输出7,后面是符号“+”,进栈。

 

       c.第三个字符是“(”,依然是符号,因其只是左括号,还没有配对,故进栈。

 

       d.第四个字符是数字5,输出,总表达式为7 5,接着是“-”,进栈。

 

       e.接下来是数字1,输出,总表达式为7 5 1,后面是符号“)”,此时,我们需要去匹配此前的“(”,所以栈顶依次出栈,并输出,直到“(”出栈为止。此时左括号上方只有“-”,因此输出“-”。总的表达式为7 5 1 -。

 

       f.接着是数字3,输出,总的表达式为7 5 1 - 3.紧接着是符号“*”,因为此时的栈顶符号为“+”号,优先级低于“*”,因此不输出,“*”进栈。

 

       g.之后是符号“+”,此时当前栈顶元素“*”比这个“+”的优先级高,因此栈中元素出栈并输出(没有比“+”更低的优先级,所以全部出栈),总输出表达式为7 5 1 - 3 * +。然后将当前这个符号“+”进栈。

 

       h.紧接着数字9,输出,总表达式为7 5 1 - 3 * + 9。后是符号“/”,所以“/”进栈。

 

       i.最后一个数字2,输出,总的表达式为7 5 1 - 3 * + 9 2。

 

       j.因已经到最后,所以将栈中符号全部出栈并输出。

       所以最终后缀表达式结果为:7 5 1 - 3 * + 9 2 / +

(3)、真分数计算:先将真分数转化为浮点数,进行浮点数的四则运算,再通过转化函数将结果的浮点数转化为分数。

(4)、功能选择:给予用户相关指引输入数字进行功能选择 

 

4、代码说明

(1)、题目生成函数

void create()	//生成	
{
	int x;	//被操作数 
	int y;	//操作数 
	int z;	//运算符 + - * / ^ 
	int w;	//运算符+ - 
	int bracket;	//括号
    int b_flag=1;
	int len;	//表达式长度 
	int temp;  
    
    len=rand()%1+2;
    
   ……

}  

 

(2)、表达式求值

操作符优先级比较

int mycmp(char a, char b) {
    if(b == '(')
        return 1;//左括号直接入栈
    else if((b == '^') &&(a == '+' || a == '-' || a == '*' || a == '/' || a == '('))
    	return 1;//^优先级高于+、-、*、/、(,入栈
    else if((b == '*' || b == '/') &&(a == '+' || a == '-' || a == '('))
        return 1;//*、/优先级高于+、-、(,入栈
    else if((b == '+' || b == '-') && (a == '('))
        return 1;//+、-优先级高于(,入栈
    else
        return 0;
} 

 

中缀表达式转后缀表达式

/*中缀表达式转后缀表达式
 中缀表达式之间无分割
 后缀表达式操作数、操作符之间用空格分割,便于区分不同操作数*/
void infix_to_suffix(char* infix, char* suffix) {
    int i, k, j=0, top=0;
    char stack[1000];//存储运算符的栈

    for(i=0; infix[i]!='\0'; i++) {
        if(infix[i] >= '0' && infix[i] <= '9') {
            suffix[j++] = infix[i];//操作数则直接输出
        } else {
            if(i != 0 && infix[i-1] >= '0' && infix[i-1] <= '9') {
                suffix[j++] = ' ';//操作数后补充空格分割
            }
            if(infix[i] == ')') {
                //遇到右括号则一直弹出直到左括号,但左括号不输出
                while(stack[top-1] != '(') {
                    suffix[j++] = stack[--top];
                    suffix[j++] = ' ';
                }
                top--;
            } else if(top == 0 || mycmp(stack[top-1], infix[i])) {
                //栈为空或当前操作符的优先级高于栈顶操作符,当前操作符入栈
                stack[top++] = infix[i];
            } else {
                //当前操作符优先级等于或低于栈顶操作符则弹出栈顶
                while(!mycmp(stack[top-1], infix[i])) {
                    suffix[j++] = stack[--top];
                    suffix[j++] = ' ';
                    if(top == 0)
                        break;
                }
                stack[top++] = infix[i];//当前操作符入栈
            }
        }
    }
    //补充空格分割
    if(suffix[j-1] != ' ') {
        suffix[j++] = ' ';
    }
    //如果操作符栈不为空,弹出所有操作符
    while(top != 0) {
        suffix[j++] = stack[--top];
        suffix[j++] = ' ';
    }
    suffix[j] = '\0';
}

  

后缀表达式求值

double suffix_value(char* suffix) {
    int i, j;
    char op;
    double stack[1000];
    int top = 0;
	double value = 0;
    
    ……

}

 

(3)、求最大公因数函数,辅助真分数计算

int gcd(long int m,long int n)
{
    while(m%n!=0){
        int t=m%n;
        m=n;
        n=t;
    }
    return n;
}

 

(4)、功能选择

printf("输入0表示生成题目,输入1表示答题,输入2表示求值\n");
(scanf("%d",&lab))

 

printf("输入生成的题目数量,题目数量小于1000:\n");
scanf("%d",&num);

 

printf("输入答案(答案可以用分数或者小数表示):\n");				
scanf("%s",ans);	//输入答案,可能为带/号的表达式

 

(5)、接受用户答案,统计对错题数

my_answer=atof(ans);

if( fabs(my_answer-right_answer )<inf){	
					printf("right!\n");
					score++;
				} 
				
				else{
					printf("wrong!\n");
					printf("my answer is %s\n",ans);
					float_to_fraction(right_answer);
					
				}

printf("得分:%d / %d",score,num);

  

 

 

 

 

 

posted on 2018-05-10 23:31  小组博客  阅读(134)  评论(0)    收藏  举报

导航