结对同学:姜珊
目录:
1.需求分析
2.基本设计
3.代码说明
4.测试运行
5.重难点知识
6.缺点改进及体会
1.需求分析:
作业链接:https://edu.cnblogs.com/campus/nenu/SWE2017FALL/homework/997
功能一和功能二其实可以合并成为一个功能,就是计算带括号的四则运算式,并对结果进行判断和输出。
功能三是利用输入参数来进行出题并输出。
2.基本设计
由需求分析可以得到,可以根据参数个数来执行某一程序段。
对于功能一二,只有一个参数就是文件名,直接输入f4并回车即可运行。
对于功能三,要输入三个参数如:f4 –c 2,其中-c后边的数字要当作程序体中的循环次数,完成输出个数的限定。
3.代码说明
地址:https://git.coding.net/immixiaomi/f4-mhjs.git
首先定义了字符类型的栈及相关操作,在将中序表达式转化为后序表达式时要用到:
typedef int Status; typedef char ElemType; typedef struct { ElemType data[MAXSIZE]; int top;//栈顶指针 }Stack; Status InitStack(Stack *S)//初始化 { int i; for(i = 0; i < MAXSIZE; i++) S->data[i] = NULL; S->top = -1; return 1; } Status CreateStack(Stack *S,int n)//创建一个长度为n的堆栈 { if(n>MAXSIZE || n<1) { printf("输入长度有误! "); return -1; } srand(time(0)); int i; for(i = 0; i < n; i++) { S->data[i] = rand()%100+1; } S->top = n-1; return 1; } Status push(Stack *S,ElemType e)//压栈操作 { if(MAXSIZE-1 == S->top) { printf("栈已满 "); return -1; } ++(S->top); S->data[S->top] = e; return 1; } Status pop(Stack *S,ElemType *e)//出栈 { if(-1 == S->top){ printf("栈为空! "); return -1; } *e = S->data[S->top]; --(S->top); return 1; }
GetStr()函数是自动生成字符串的函数,参数是空字符数组,通过随机数的产生,并将随机数用itoa()函数转化成字符型,加入随机的运算符产生了中序表达式。先产生了表达式再向其中加入括号,括号都是成对加入,完成了带括号表达式的构建。
void GetStr(char *str)//构建随机串,并添加括号 { char str1[1] = ""; int a, b, c, d; char op1, op2, op3; int i; srand((int)time(0)); a = (int)(rand()%10);//四个变量 b = (int)(rand()%10); c = (int)(rand()%10); d = (int)(rand()%10); i = (int)(rand()%4);//三个操作符 switch(i) { case 0: op1 = '+'; break; case 1: op1 = '-'; break; case 2: op1 = '*'; break; case 3: op1 = '/'; break; } i=(int)(rand()%4); switch(i) { case 0: op2 = '+'; break; case 1: op2 = '-'; break; case 2: op2 = '*'; break; case 3: op2 = '/'; break; } i=(int)(rand()%4); switch(i) { case 0: op3 = '+'; break; case 1: op3 = '-'; break; case 2: op3 = '*'; break; case 3: op3 = '/'; break; } itoa(a, str1, 10); strcpy(str, str1); str[1] = op1; itoa(b, str1, 10); strcat(str, str1); str[3] = op2; itoa(c, str1, 10); strcat(str, str1); str[5] = op3; itoa(d, str1, 10); strcat(str, str1); for(int j = 0; j < 7; j++) { if(str[j] == '/') { int e; e = (int)(rand()%9)+1; itoa(a, str1, 10); str[j+1] = str1[0]; } } int j, k;//左括号右括号 int flag = 0; j = (int)(rand()%3); int length = 8; if(j == 0)//位置1加不加左括号的判定 { k = (int)(rand()%4); if(k != 3&&flag != 2) { for(int i = length;i > 0;i--)//向坐标0处插入括号 { str[i] = str[i-1]; } str[0] = '('; flag++; length++; int l = (int)(rand()%4); if(l < 2) { for(int i = length; i > 4; i--) { str[i] = str[i-1]; } str[4] = ')'; flag--; length++; for(int i = length;i > 6;i--) { str[i] = str[i-1]; } str[6] = '('; flag++; length++; for(int i = length;i > 10;i--) { str[i] = str[i-1]; } str[10] = ')'; flag--; length++; } else if(l = 2) { for(int i = length; i > 4; i--) { str[i] = str[i-1]; } str[4] = ')'; flag--; length++; } else if(l = 3) { for(int i = length; i > 6; i--)//插入括号 { str[i] = str[i-1]; } str[6] = ')'; flag--; length++; } } else if(k != 2&&flag != 2) { for(int i = length+1; i > 1; i--)//向坐标0,1处插入俩左括号 { str[i] = str[i-2]; } str[0] = '('; str[1] = '('; flag = flag+2; length = length+2; for(int i = length; i > 5; i--) { str[i] = str[i-1]; } str[5] = ')'; flag--; length++; for(int i = length; i > 8; i--) { str[i] = str[i-1]; } str[8] = ')'; flag--; length++; } } else if(j == 1) { k=(int)(rand()%4); if(k != 3&&flag != 2) if(0) { for(int i = length; i > 2; i--)//向坐标2处插入括号 { str[i] = str[i-1]; } str[2] = '('; flag++; length++; } else if(k != 2&&flag != 2) { for(int i = length+1; i > 3; i--)//向坐标2,3处插入俩左括号 ,只能接着向6和8(原坐标)添加括号 { str[i] = str[i-2]; } str[2] = '('; str[3] = '('; flag = flag+2; length = length+2; for(int i = length; i > 7; i--) { str[i] = str[i-1]; } str[7] = ')'; flag--; length++; for(int i = length;i > 10;i--) { str[i] = str[i-1]; } str[10] = ')'; flag--; length++; } } else if(j == 2) { k = (int)(rand()%4); if(k != 3&&flag != 2) { for(int i = length; i>4; i--)//向坐标4处插入括号 { str[i] = str[i-1]; } str[4] = '('; flag++; length++; //str4 插入左括号一个 for(int i = length; i>8; i--) { str[i] = str[i-1]; } str[8] = ')'; flag--; length++; } } for(i = 0; i < length-1; i++) { printf("%c",str[i]); } printf("="); }
Translate()函数是将中序表达式转化为后序表达式,参数是两个字符串,分别是旧串和转化后的新串。用栈进行操作,并对括号进行配对取出,转化成为没有括号的逆波兰表达式。
int Translate(char *str,char *exp)//中缀表达式转后缀表达式 { //新建一个栈,来存储符号 char e; Stack S; if(InitStack(&S) != 1) { printf("初始化栈失败! "); } //当带转换的字符串*mid未终止时,循环处理 while(*str) { //如果是数字,则直接输出 if(*str >= '0' && *str <= '9') { *(exp++) = *(str++); continue; }else if(*str == '+' || *str == '-' || *str == '*' || *str == '/' || *str == '(' || *str == ')') { //输入的是合法运算符号,比较之前是否有更高优先级的符号 if(S.top == -1 || '(' == *str) { //当符号栈为空或遇到左括号时,符号入栈 push(&S, *(str++)); continue; } if(')' == *str) { //遇到右括号时,栈顶元素依次出栈;直到遇到第一个左括号时结束 pop(&S, &e); *(exp++) = e; while(pop(&S, &e) && e != '(') { *(exp++) = e; } // printf("%c ",e); str++; continue; } //后续的处理都要取出临时的栈顶元素,与当前输入的符号*mid相比较;当临时栈顶元素优先级大于等于输入符号的优先级时,出栈;否则符号入栈(已经弹出一个,记得把弹出的元素也入栈) pop(&S,&e); if('+' == *str || '-' == *str) { if(e == '(') { push(&S, '('); push(&S, *(str++)); continue; } else { *(exp++) = e; push(&S, *(str++)); continue; } } else if('*' == *str || '/' == *str) { if('*' == e || '/' == e) { *(exp++)=e; push(&S, *(str++)); continue; } else { push(&S, e); push(&S, *(str++)); continue; } } } else { printf("error%c ", *str); return -1; } } //当待转换的字符已经结束时,符号栈至少还有一个元素(中缀表达式的特点:数字结尾;后缀表达式以符号结尾);将栈中的元素依次出栈 while(S.top != -1) { pop(&S, &e); *(exp++) = e; } //字符串的结束符! *exp = '