欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

蓝桥杯 小计算器 C++详细说明

程序员文章站 2022-06-08 22:13:48
...

问题描述

模拟程序型计算器,依次输入指令,可能包含的指令有
    1. 数字:'NUM X',X为一个只包含大写字母和数字的字符串,表示一个当前进制的数
    2. 运算指令:'ADD','SUB','MUL','DIV','MOD',分别表示加减乘,除法取商,除法取余
    3. 进制转换指令:'CHANGE K',将当前进制转换为K进制(2≤K≤36)
    4. 输出指令:'EQUAL',以当前进制输出结果
    5. 重置指令:'CLEAR',清除当前数字


    指令按照以下规则给出:
    数字,运算指令不会连续给出,进制转换指令,输出指令,重置指令有可能连续给出
    运算指令后出现的第一个数字,表示参与运算的数字。且在该运算指令和该数字中间不会出现运算指令和输出指令
    重置指令后出现的第一个数字,表示基础值。且在重置指令和第一个数字中间不会出现运算指令和输出指令
    进制转换指令可能出现在任何地方


运算过程中中间变量均为非负整数,且小于2^63。
以大写的'A'~'Z'表示10~35
输入格式
第1行:1个n,表示指令数量
第2..n+1行:每行给出一条指令。指令序列一定以'CLEAR'作为开始,并且满足指令规则
输出格式
依次给出每一次'EQUAL'得到的结果
样例输入
7
CLEAR
NUM 1024
CHANGE 2
ADD
NUM 100000
CHANGE 8
EQUAL

样例输出
2040

看到这题时的问题:

  • 问题一:
    可以转换的进制为(2 <= k <= 36),有没有人看到这个就奔溃了,我真得写这么多进制转换函数吗?不写的话怎么办?可以写一个进制转换模板函数吗?可以的话怎么写?

    解决:每当遇到复杂问题,我们都喜欢往简单像。所以,我们在运算时统一用10进制数算,等到输出的时候转换成相应进制就行。是不是就简单很多了。

int base = m;  //base为进制数,m可以为2~36
举例:
    int base = 10;
    string s = "1024";
    long long  x = 0;
    for(int i = 0;i < s.size();i++){
        long  long temp = isdigit(s[i]) ?  s[i] - '0' : x = s[i] + 10 - 'A';
        //最重要的是这个公式,这个公式能使其他进制数转换为10进制数
        x = x * base + temp;//知道这个公式怎么推吗?欢迎留言评论^ ^
    }
    
总结:
    记住这个公式。这就是进制转换模板,这个函数的参数是什么,怎样和其他函数对接。
    见下文的设计思想。
  • 问题二: 怎样实现从10进制转换成其他进制
    解决:
    1、使用一个vector来存放的内容。
    2、 % 其他进制数 (% 8等)放入vector中,如果余数大于10记得转换成相应的字母。
    3、vector中的内容逆序输出才是对应的进制数
void print(){
    vector<char> v;
    long long x = sum;//所要转换的数,可能是做了运算后的数,也可能是clear后的第一个数。
    while(x){
        int cur = x % base;
        if(cur >= 0 && cur <= 9){
            //比如cur = 1 和 cur + '0' 读者自行执行printf("%d\n",cur);和printf("%c\n",cur+'0');有助于理解
            v.push_back(cur+'0');
        }else{
            //为什么要减10呢?如果不减的话对应不上ASCLL码。就上面两个printf输出的结果不一样,10-35已经是36个数了,减了10后刚好够26个字母。
            v.push_back(cur-10+'A');
        }
        x /= base;  
    }
    //注意!!我们运算后sum = 0 或者是第一个数给的是0
    if(v.size() == 0)
        cout << "0" << endl;
    for(int i = vector.size() - 1;i >= 0;i--){//有的地方判断条件可能是~i,意思就是说i=-1的时候退出。
    因为-1的机器码(负数的机器码是 补码)是全1,~称为按位取反,取反就全0,就不执行for循环了。
        cout << v[i];
    }
    cout << endl;
}

这两个问题都解决了就可以写main函数了

#include <bits/stdc++.h>
using namespace std;

int base = 10;		//初始为10
long long sum = 0;	//运算后的数 

//输出相应进制数
void print(){
    vector<char> v;
    long long x = sum;
    while(x){
        int cur = x % base;
        if(cur <= 9){
            v.push_back(cur+'0');
        }else{
            v.push_back(cur-10+'A');
        }
        x /= base;  
    }
    if(v.size() == 0){
        cout << "0" << endl;
        return;
    }
    for(int i = v.size() - 1;i >= 0;i--){
        cout << v[i];
    }
    cout << endl;
} 


//转换为10进制
long long  get_decimal(){
	string s;
	cin >> s;
    long long  x = 0;
    for(int i = 0;i < s.size();i++){
        long long temp = isdigit(s[i]) ? s[i] - '0' : s[i] + 10 - 'A';
    	x = x * base + temp;
	}
    return x;
} 


int main(){
	int n;			//指令数
	cin >> n;
	string op;		//指令 
	int opi = 0;	//指令下标 
	while(n--){
		cin >> op;
		if(op == "CLEAR") opi = sum = 0;
		else if(op == "CHANGE") cin >> base;
		else if(op == "EQUAL") print();
		else if(op == "ADD") opi = 2;
		else if(op == "SUB") opi = 3;
		else if(op == "MUL") opi = 4;
		else if(op == "DIV") opi = 5;
		else if(op == "MOD") opi = 6;
		else if(op == "NUM"){
			switch(opi){
				case 0: sum = get_decimal(); break;//CLEAR后的第一个数 
				case 2: sum += get_decimal();break;
				case 3: sum -= get_decimal();break;
				case 4: sum *= get_decimal();break;
				case 5: sum /= get_decimal();break;
				case 6: sum %= get_decimal();break;
			}
		}
	} 
	
	return 0;
} 
相关标签: 蓝桥杯