1、输入一串整数,输入指令。
要求:(1)输入a t,在这串整数后添加整数t。(2)输入c\m\n,用n替换m。(3)输入d t,删除t。(4)输入s,排序。
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int parseInt(string b){
char a = b[0];//switch-case中只能接受int\char类型,故而不能直接用string,这里使用了讨巧的方法
switch(a){
case '0':return 0;break;
case '1':return 1;break;
case '2':return 2;break;
case '3':return 3;break;
case '4':return 4;break;
case '5':return 5;break;
case '6':return 6;break;
case '7':return 7;break;
case '8':return 8;break;
case '9':return 9;break;
default: return -1;
}
}
void replaceNum(int &num, int m, int n){//n替换m
int sum=0; //思路来源图1
int bei = 1;
while(num){
int mo = num%10;
if(mo==m){
sum = n*bei+sum;
}else{
sum = mo*bei+sum;
}
num=num/10;
bei*=10;
}
num = sum;
}
void addT(int &num, int t){
num=num*10+t;
}
void optionA(int &num){
int t;
cin>>t;
addT(num, t);
cout<<"结果是:"<<num<<endl;
}
void optionC(int &num){
// \m\n,用n替换m
string s;
int index;
cin>>s;
for(int i=1;i<s.length();i++){
if(s[i]=='\\'){
index=i;
break;
}
}
int m = parseInt(s.substr(1,index-1));
int n = parseInt(s.substr(index+1));
//可以直接使用字符串,然后我们用replace函数
replaceNum(num, m, n);
cout<<"结果是:"<<num<<endl;//输出结果
}
void deleteT(int &num, int t){
int sum=0, bei=1;
while(num){ //思路来源图2
int mo = num%10;
if(mo!=t){//当等于t时候什么都不做 ,也就是图2中的,遇到2 sum=sum
sum = mo*bei+sum;
bei*=10;
}
num=num/10;
}
num = sum;
}
void optionD(int &num){//3.输入d t,删除t。
int t;
cin>>t;
deleteT(num, t);
cout<<"结果是:"<<num<<endl;//输出结果
}
void assemble(vector<int>& v, int num){
while(num){
int mo = num%10;
v.push_back(mo); //思路来源,利用vector可以用sort函数
num/=10;
}
sort(v.begin(),v.end());
}
void sortNum(int &num){
vector<int> v;
assemble(v, num);
for(vector<int>::iterator it=v.begin();it!=v.end();it++){
cout<<*it;
}
cout<<endl;
}
int main()
{
while(1){
cout<<"\n输入一串整数,输入指令。要求:\n1.输入a t,在这串整数后添加整数t。\n2.输入c \\m\\n,用n替换m。\n3.输入d t,删除t。\n4.输入s,排序。\n请先输入一串整数:";
//加入两杠\\是因为转义字符
int num;
cin>>num;
char type;
cout<<"请输入操作指令:";
cin>>type;
if(type=='a'){
optionA(num);
}else if(type=='c'){
optionC(num);
}else if(type=='d'){
optionD(num);
}else if(type=='s'){
sortNum(num);
}else{
return 0;
}
}
return 0;
}
2、输入表达式,输出值。分两种情况:中缀表达式和后缀表达式。
中缀表达式求值:先将中缀表达式建立二叉树转后缀表达式,然后再求值。
尝试1:
#include <iostream>
#include <string>
#include <cmath>
#include <cstdlib>//sum1=atof(t1.c_str());
using namespace std;
//后缀表达式求值,这种方式的弊端很明显,只能计算单个位置的数据,不能出现多位数和小数,原因是我这里每次取数是expression[i]造成的
double postfix_expression(string expression){
//56+2*3+
double stack[20];//操作数栈
int top = -1;//栈顶指针
for(int i=0;i<expression.length();i++){
if(expression[i]=='+'){
double d = stack[top];//栈顶指针在top
top--;
double c = stack[top];
stack[top]=d+c;
cout<<d<<"+"<<c<<"="<<stack[top]<<endl;
}else if(expression[i]=='-'){
double d = stack[top];
top--;
double c = stack[top];
stack[top]=c-d;
cout<<c<<"-"<<d<<"="<<stack[top]<<endl;
}else if(expression[i]=='*'){
double d = stack[top];
top--;
double c = stack[top];
stack[top]=c*d;
cout<<d<<"*"<<c<<"="<<stack[top]<<endl;
}else if(expression[i]=='/'){
double d = stack[top];
top--;
double c = stack[top];
stack[top]=c/d;
cout<<c<<"/"<<d<<"="<<stack[top]<<endl;
}else if(expression[i]>='0' and expression[i]<='9'){
top++;
string s = expression.substr(i,1);
double c = atof(s.c_str());
stack[top]=c;
}else{
cout<<"输入错误!"<<endl;
exit(0);
}
}
return stack[top--];
}
int main()
{
// string ex;
// cout<<"请输入后缀表达式:";
// cin>>ex;
//用例:3*(5+4)/8+4*(5+2)
cout<<postfix_expression("54+3*8/52+4*+")<<endl;
return 0;
}
猜想,我们对数字的判断应该在之前就判断完毕,因为后缀表达式中,如:54+3*8/52+4*+,是比较难确定54还是5 4 当然可以用操作符的个数匹配,但是比较麻烦。这里,我们可以用中缀表达式,也就是原来输入的数据表达式,然后我们截取数据放入集合中,集合的类型是vector<string>,我们在使用后缀表达式的时候,转换数据就会比较方便。下面关键是如何处理由中缀表达式向后缀表达式转化。
参考数据结构:
需要用操作符的优先级进行栈运算。用icp(in coming priority)表示当前扫描到的运算符的优先级,用isp(in stack priority)表示该运算符进栈后的优先级。
操作符 |
# |
( |
* / |
+ - |
) |
isp |
0 |
1 |
5 |
3 |
6 |
icp |
0 |
6 |
4 |
2 |
1 |
举例说明:3*(5+4)/8+4*(5+2)
中缀表达式:3*(5+4)/8+4*(5+2) 后缀表达式:354+*8/452+*+
步骤 |
扫描项 |
项类型 |
动作 |
字符栈内内容 |
输出 |
0 |
|
|
‘#’进栈,读取下一字符 |
# |
|
1 |
3 |
操作数 |
直接输出 |
# |
3 |
2 |
* |
操作符 |
isp(#)<icp(*),进栈 |
#* |
|
3 |
( |
操作符 |
isp(*)<icp((),进栈 |
#*( |
|
4 |
5 |
操作数 |
直接输出 |
#*( |
5 |
5 |
+ |
操作符 |
isp(()<icp(+),进栈 |
#*(+ |
|
6 |
4 |
操作数 |
直接输出 |
|
4 |
7 |
) |
操作符 |
isp(+)>icp()),出栈 |
#*( |
+ |
|
|
|
isp(()==icp()),退栈 |
#* |
|
8 |
/ |
操作符 |
isp(*)>icp(/),出栈 |
# |
* |
|
|
|
isp(#)<icp(/),出栈 |
#/ |
|
9 |
8 |
操作数 |
直接输出 |
|
8 |
10 |
+ |
操作符 |
isp(/)>icp(+),出栈 |
# |
/ |
11 |
|
|
isp(#)<icp(+),进栈 |
#+ |
|
12 |
4 |
操作数 |
直接输出 |
|
4 |
13 |
* |
操作符 |
isp(+)<icp(*),进栈 |
#+* |
|
14 |
( |
操作符 |
isp(*)<icp((),进栈 |
#+*( |
|
15 |
5 |
操作数 |
直接输出 |
|
5 |
16 |
+ |
操作符 |
isp(()<icp(+),进栈 |
#+*(+ |
|
17 |
2 |
操作数 |
直接输出 |
|
2 |
18 |
) |
操作符 |
isp(+)>icp()),出栈 |
#+*( |
+ |
|
|
|
isp(()==icp()),退栈 |
#+* |
|
19 |
# |
操作符 |
isp(*)>icp(#),出栈 |
#+ |
* |
|
|
|
isp(+)>icp(#),出栈 |
# |
+ |
|
|
|
isp(#)==icp(#),退栈结束 |
#) |
|
就可以得到中缀表达式,所以这里需要使用优先级比较+栈
#include <iostream>
#include <string>
#include <cmath>
#include <vector>
#include <cstdlib>//sum1=atof(t1.c_str());
using namespace std;
/*
操作符 # ( * / + - )
isp 0 1 5 3 6
icp 0 6 4 2 1
*/
//四则运算,栈内>入栈,而且*/一定高于+-;括号,栈内<入栈, 站内尾大,入栈头大,占两端
// 前期思考数据封装函数,最后演化成 transform_postfix 中的中心架构
vector<double> data_package(string expression){
vector<double> vc;
int index=0, count=0;//记录需要截取字符串的下标位置
for(int i=0;i<expression.length();i++){
//3*(5+4)/8+4*(5+2)
if(expression[i]=='+' or expression[i]=='-' or expression[i]=='*' or expression[i]=='/' or expression[i]==')' or expression[i]=='('){
if(count!=0){
string s=expression.substr(index, count);//使用截取而不是直接expression[i],是因为写入字符,是字符地址后面的一大坨字符(首地址)
double num = atof(s.c_str());
vc.push_back(num);
}
index=i+1;
count=0;
}
else {
count++;
}
}
return vc;
}
//3*(5+4)/8+4*(5+2)
//为了方便+-*/()表示为:335516 224461
int get_isp(char a){
if(a=='+' or a=='-')
return 3;
else if(a=='*' or a=='/')
return 5;
else if(a=='(')
return 1;
else if(a==')')
return 6;
else if(a=='#')
return 0;
}
int get_icp(char a){
if(a=='+' or a=='-')
return 2;
else if(a=='*' or a=='/')
return 4;
else if(a=='(')
return 6;
else if(a==')')
return 1;
else if(a=='#')
return 0;
}
string transform_op_stack_to_string(char a){
//op_stack[top]
if(a=='+')
return "+";
else if(a=='-')
return "-";
else if(a=='*')
return "*";
else if(a=='/')
return "/";
}
//思路来源于上面的:data_package
string transform_postfix(string expression){
//这里也要完成表达式的封装vector<string>
vector<double> vc = data_package(expression);
char op_stack[20];//+-*/():335516 224461
int top = -1;
top++;
op_stack[top]='#';
string str="";
int index=0, count=0;//记录需要截取字符串的下标位置
int i=0;
while(top!=-1){
if(i==expression.length()){
expression.append("#");//因为栈可能没出完,而表达式判断已经到了末尾
}
if(expression[i]=='+' or expression[i]=='-' or expression[i]=='*' or expression[i]=='/' or expression[i]==')' or expression[i]=='#' or expression[i]=='('){
//数字在前
if(count!=0){
string s=expression.substr(index, count);
str.append(s);
str.append(" "); //数字,直接输出
}
index=i+1;
count=0;
//符号判断在后
//isp icp 大,进;小,顶出;等,退
if(get_isp(op_stack[top])<get_icp(expression[i])){
top++;
op_stack[top]=expression[i];
}else if(get_isp(op_stack[top])>get_icp(expression[i])){
bool flag = true;//是否循环
while(flag){//使用标识,进栈或者退栈,就退出循环
if(get_isp(op_stack[top])>get_icp(expression[i])){
//小 ,顶出
str.append(transform_op_stack_to_string(op_stack[top])+" ");
//这里之所以要把char 转为 string ,是因为使用char 数组,加入的是该地址后的所有的字符
// cout<<op_stack[top]<<"顶出"<<"此时的比较元素是:"<<expression[i]<<endl;
top--;
}else if(get_isp(op_stack[top])<get_icp(expression[i])){//大,进
top++;
op_stack[top]=expression[i];
flag = false;//不再循环
// cout<<op_stack[top]<<"进栈"<<endl;
}else if(get_isp(op_stack[top])==get_icp(expression[i])){
flag = false;//不再循环
// cout<<op_stack[top]<<"退栈"<<endl;
top--;//等,退
}
}
}else if(get_isp(op_stack[top])==get_icp(expression[i])){
top--;//等,退
}
}else {
count++;
}
i++;
}
cout<<"后缀表达式的结果:"<<str<<endl;
return str;
}
//初始版本(已抛弃):后缀表达式求值,这种方式的弊端很明显,只能计算单个位置的数据,不能出现多位数和小数,原因是我这里每次取数是expression[i]造成的
double postfix_expression(string expression){
//56+2*3+
double stack[20];//操作数栈
int top = -1;//栈顶指针
cout<<"计算的过程如下:"<<endl;
for(int i=0;i<expression.length();i++){
if(expression[i]=='+'){
double d = stack[top];//栈顶指针在top
top--;
double c = stack[top];
stack[top]=d+c;
cout<<d<<"+"<<c<<"="<<stack[top]<<endl;
}else if(expression[i]=='-'){
double d = stack[top];
top--;
double c = stack[top];
stack[top]=c-d;
cout<<c<<"-"<<d<<"="<<stack[top]<<endl;
}else if(expression[i]=='*'){
double d = stack[top];
top--;
double c = stack[top];
stack[top]=c*d;
cout<<d<<"*"<<c<<"="<<stack[top]<<endl;
}else if(expression[i]=='/'){
double d = stack[top];
top--;
double c = stack[top];
stack[top]=c/d;
cout<<c<<"/"<<d<<"="<<stack[top]<<endl;
}else if(expression[i]>='0' and expression[i]<='9'){
top++;
string s = expression.substr(i,1);
double c = atof(s.c_str());
stack[top]=c;
}else{
cout<<"输入错误!"<<endl;
exit(0);
}
}
return stack[top--];
}
//改进
double postfix_expression_fix(string expression){
//56+2*3+
double stack[20];//操作数栈
int top = -1;//栈顶指针
int count=0, index=0;
//测试的结果:3 5 4 + * 8 / 4 5 2 + * + 用空格分割
for(int i=0;i<expression.length();i++){
if(expression[i]=='+' or expression[i]=='-' or expression[i]=='*' or expression[i]=='/' or expression[i]==')' or expression[i]==' ' or expression[i]=='('){
//数字在前
if(count!=0){
string s=expression.substr(index, count);
// cout<<"操作数:"<<s<<endl;//测试
top++;
stack[top]=atof(s.c_str()); //字符串转化为double,加入栈
}
index=i+1;
count=0;
//判断符号
if(expression[i]=='+'){
double d = stack[top];//栈顶指针在top
top--;
double c = stack[top];
stack[top]=d+c;
cout<<d<<"+"<<c<<"="<<stack[top]<<endl;
}else if(expression[i]=='-'){
double d = stack[top];
top--;
double c = stack[top];
stack[top]=c-d;
cout<<c<<"-"<<d<<"="<<stack[top]<<endl;
}else if(expression[i]=='*'){
double d = stack[top];
top--;
double c = stack[top];
stack[top]=c*d;
cout<<d<<"*"<<c<<"="<<stack[top]<<endl;
}else if(expression[i]=='/'){
double d = stack[top];
top--;
double c = stack[top];
stack[top]=c/d;
cout<<c<<"/"<<d<<"="<<stack[top]<<endl;
}else if(expression[i]>='0' and expression[i]<='9'){
top++;
string s = expression.substr(i,1);
double c = atof(s.c_str());
stack[top]=c;
}
}else{
count++;
}
}
return stack[top--];
}
int main()
{
string expression;
cout<<"请输入中缀表达式:";
cin>>expression;
//用例:3*(5+4)/8+4*(5+2)
string postfix = transform_postfix(expression);//后缀表达式:354+*8/452+*+
double result = postfix_expression_fix(postfix);
cout<<"表达式:"<<expression<<",计算的结果是:"<<result<<endl;
return 0;
}
下面是使用电脑计算器计算的结果:
作者:无涯明月
上篇:北理复试上机题2009年