项目题目1——字符串相关操作

5.8晚上的考试,特此总结一下


字符串处理 

虚拟指令执行

请设计一种虚拟机解释器,能解析并执行以下虚拟指令。

虚拟机约定:32位整形计数器:a0,a1……a31,共32个寄存器;

整个虚拟机只有寄存器和立即数参与计算。

规则集(dst 一定为寄存器 ,src为寄存器或十进制正整数,运算结果存在负数场景);

1. MOV dst src        

        含义:dst = src

2.ADD dst src0 src1

        含义:dst = src0+src1

3.SUB dst src0 src1

        含义:dst = src0-src1

4.MUL dst src0 src1

        含义:dst = src0*src1

5.DIV dst src0 src1

        含义:dst = src0/src1(结果向下取整)

6.PRINT dst

        含义:打印dst寄存器的值

约束:不用考虑计算溢出(用例保证),指令数最多100条,至少一条PRINT指令,寄存器保证先赋值再引用。不用考虑小数跟除0。

样例1

输入:

MOV a1 100

MOV a2 200

ADD a3 a1 100

SUB a4 a3 a2

PRINT a4

输出

0

知识点

字符串包含空格输入

string a;
getline(cin,a);

getline() 函数可以逐行读入,包含制表符,空格;以回车键结束

具体细节可以看我的另一篇博客 http://t.csdnimg.cn/hUmVJc++与c的字符串类型数据结构探究-CSDN博客http://t.csdnimg.cn/hUmVJ

字符串多行输入

题目用例肯定不止一行,那么如何实现多行输入呢?

当然是用循环啦

那么结束的条件是什么呢

就是输入结束=什么也不输入的时候

这时我们就想到了一个c++函数empty()

具体含义可以参考这篇博客 C++ String empty()用法及代码示例 - 纯净天空 (vimsky.com)

 此函数检查字符串是否为空。函数返回一个布尔值 true 或 false

string a;
while(getline(cin,a)){
    if(a.empty())
        break;
    else{
        //执行之后的操作
    }
}

这样就可以实现多行输入字符串啦

代码实现

函数功能

  • string iswhat(string a) 获取输入字符串的操作类型
  • int dstnumwhat(string a) 获取dst的寄存器号(第一个参数为寄存器)
  • bool isrightorregister(string a,int m) 判断2/3参数是立即数还是寄存器 参数m含义:要判断第2个参数 输入1;要判断第3个参数 输入2
  • int isrightnum(string a,int m) 参数m含义和上同 获取立即数的数字值
  • int isregister(string a,int m) 参数m含义和上同 获取寄存器号
  • int dowhatandreturn(string a,char op) 这个函数是我觉得我思路的突破,通过传入操作的方法,实现对应的操作,返回参数2和参数3 通过op操作后的值,在主函数调用,传入全局变量对应dst寄存器中

还有参数的话就是每次输入字符串string a后对其进行操作;

全局变量 arr[32]数组,记录32位寄存器的值。

比较值得说的就是,之前我的代码是按下标取数字的(开始以为输入的都是3位数,没细细审题)

后来我的改进就是以空格(的个数)为判断依据(空格也可以为循环退出的条件)

完整代码

大概300行吧,感觉考试120min真的很难写出来这么完整的工程代码

#include<iostream>
#include<cstdlib>
using namespace std;

static int arr[32];//32个寄存器 保存对应值 

//获取方法的函数 MOV/ADD/SUB/MUL/DIV/PRINT
string iswhat(string a){
    int n = a.size() ;
    string s;
    for(int i=0;;i++){
    	if(a[i]!=' '){
    		s+=a[i];
		}
		else if(a[i]==' ')	
			break;
	}
    return s;
}
int dstnumwhat(string a) {//获取dst的寄存器号
	string cnt="";
	int res ,k ;
	for(int i=4;;i++) {
		if(a[i]=='a'){ 	//到达a位置
			k = i+1;
			for(k;;k++){
				if(a[k]==' ')	
					break;
				cnt+=a[k];
			}
			res = atoi(cnt.c_str() ) ;//转换为int型 
			break;
		}
	}
	return res;
}

bool isrightorregister(string a,int m) {//m表示 第一个参数or二 判断参数的类型 
	int cnt=0;
	int n = a.size() ;
	for(int i=0;i<n;i++){
		if(a[i]==' ')
			cnt++;
		if(cnt==2 && m==1){//判断第一个参数类型 
			 for(int j=i+1;;j++){
				if(a[j]==' ')
					break;//退出条件
				if(a[j]>='0' && a[j]<='9') //判断为立即数
					return true;
				else
					return false;//判断为寄存器 
			}
		}
		if(cnt==3 && m==2){//判断第二个参数类型 
			for(int j=i+1;;j++){
				if(a[j]==' ')
					break;//退出条件
				if(a[j]>='0' && a[j]<='9') //判断为立即数
					return true;
				else
					return false;//判断为寄存器 
			}
		}
	} 
}
int isrightnum(string a,int m){//取立即数的值然后返回 m表示第一个或者第二个参数 
	int res;
	int cnt=0;
	int n = a.size() ;
	string s;
	
	for(int i=0;i<n;i++){
		if(a[i]==' ')
			cnt++;
		if(cnt==2 && m==1){//第一个参数
			 for(int j=i+1;;j++){
				if(a[j]==' ')
					break;//退出条件
				//立即数
				s+=a[j]; 
			}
			res = atoi(s.c_str() ) ;
			break;
		}
		if(cnt==3 && m==2){//判断第二个参数类型 
			for(int j=i+1;;j++){
				if(a[j]==' ')
					break;//退出条件
				//立即数
				s+=a[j];
			}
			res = atoi(s.c_str() ) ;
			break;
		}
	} 
	return res;
}
int isregister(string a,int m){//取寄存器号的值然后返回 m表示第一个或者第二个参数 
	int res;
	int cnt = 0;
	int n = a.size() ;
	string s;
	int k;
	for(int i=0;i<n;i++){
		if(a[i]==' ')
			cnt++;
		if(cnt==2 && m==1){//第一个参数
			 for(int j=i+2;;j++){
				if(a[j]==' ')
					break;//退出条件
				//立即数
				s+=a[j]; 
			}
			res = atoi(s.c_str() ) ;
			break;
		}
		if(cnt==3 && m==2){//判断第二个参数类型 
			for(int j=i+2;;j++){
				if(a[j]==' ')
					break;//退出条件
				//立即数
				s+=a[j];
			}
			res = atoi(s.c_str() ) ;
			break;
		}
		
	}
	return res;
}
int dowhatandreturn(string a,char op){
	int n = a.size() ;
	int res;
	if(op=='+'){
		res = 0;
		if(isrightorregister(a,1)){//第1个数是立即数 
			res = isrightnum(a,1) ;
			if(isrightorregister(a,2)){//第2个数是立即数 
				res += isrightnum(a,2) ;
			}
			else{//第2个数是寄存器 
				int index = isregister(a,2);//寄存器下标
				res += arr[index] ;
			}
		}
		else{//第1个数是寄存器 
			int index = isregister(a,1);//寄存器下标
			res = arr[index] ;
			if(isrightorregister(a,2)){//第2个数是立即数 
				res += isrightnum(a,2) ;
			}
			else{//第2个数是寄存器 
				int index = isregister(a,2);//寄存器下标
				res += arr[index] ;
			}
		}
	}
	else if(op=='-'){
		res = 0;
		if(isrightorregister(a,1)){//第1个数是立即数 
			res = isrightnum(a,1) ;
			if(isrightorregister(a,2)){//第2个数是立即数 
				res -= isrightnum(a,2) ;
			}
			else{//第2个数是寄存器 
				int index = isregister(a,2);//寄存器下标
				res -= arr[index] ;
			}
		}
		else{//第1个数是寄存器 
			int index = isregister(a,1);//寄存器下标
			res = arr[index] ;
			if(isrightorregister(a,2)){//第2个数是立即数 
				res -= isrightnum(a,2) ;
			}
			else{//第2个数是寄存器 
				int index = isregister(a,2);//寄存器下标
				res -= arr[index] ;
			}
		}
	}
	else if(op=='*'){
		res = 1;
		if(isrightorregister(a,1)){//第1个数是立即数 
			res = isrightnum(a,1) ;
			if(isrightorregister(a,2)){//第2个数是立即数 
				res *= isrightnum(a,2) ;
			}
			else{//第2个数是寄存器 
				int index = isregister(a,2);//寄存器下标
				res *= arr[index] ;
			}
		}
		else{//第1个数是寄存器 
			int index = isregister(a,1);//寄存器下标
			res = arr[index] ;
			if(isrightorregister(a,2)){//第2个数是立即数 
				res *= isrightnum(a,2) ;
			}
			else{//第2个数是寄存器 
				int index = isregister(a,2);//寄存器下标
				res *= arr[index] ;
			}
		}
	}
	else if(op=='/'){
		res = 1;
		if(isrightorregister(a,1)){//第1个数是立即数 
			res = isrightnum(a,1) ;
			if(isrightorregister(a,2)){//第2个数是立即数 
				res /= isrightnum(a,2) ;
			}
			else{//第2个数是寄存器 
				int index = isregister(a,2);//寄存器下标
				res /= arr[index] ;
			}
		}
		else{//第1个数是寄存器 
			int index = isregister(a,1);//寄存器下标
			res = arr[index] ;
			if(isrightorregister(a,2)){//第2个数是立即数 
				res /= isrightnum(a,2) ;
			}
			else{//第2个数是寄存器 
				int index = isregister(a,2);//寄存器下标
				res /= arr[index] ;
			}
		}
	}
	return res;
}

int main()
{
    string a;
	while(getline(cin,a)){
		if(a.empty()){
			break;
		}
		
		string s;
    	int n = a.length();
    	s = iswhat(a);//获取方法类型 
		int dst = dstnumwhat(a);//获取dst寄存器号 
		if(s=="MOV"){
			if(isrightorregister(a,1)) {//是立即数 
				arr[dst] = isrightnum(a,1);//寄存器保存对应值 
			}
			else{//dst需要 赋 寄存器的值 
				arr[dst] = isregister(a,1) ;
			} 
		}
        else if(s=="ADD"){
        	int res = dowhatandreturn(a,'+');
        	arr[dst] = res;
        }
        else if(s=="SUB"){
            int res = dowhatandreturn(a,'-');
            arr[dst] = res;
        	
        }
        else if(s=="MUL"){
        	int res = dowhatandreturn(a,'*');
            arr[dst] = res;
            
        }
        else if(s=="DIV"){
            int res = dowhatandreturn(a,'/');
            arr[dst] = res;
        }
        else if(s=="PRINT"){//为输出的情况PRINT 
          	cout<<arr[dst]<<endl; 
        }
    }
    
    return 0;
}

运行结果

测试用例跑的结果

我自己编的复杂的用例(就是行数多些)

你们也可以写完之后跑一下(我的下标有点儿小问题,从1开始了)

MOV a1 100
MOV a2 200
PRINT a1
PRINT a2
ADD a3 a1 a2
SUB a4 a3 a2
ADD a5 a4 a2
SUB a6 a5 a2
ADD a7 a6 a2
SUB a8 a7 a2
ADD a9 a8 a2
SUB a10 a9 a2
ADD a11 a10 a2
SUB a12 a11 a2
ADD a13 a12 a2
SUB a14 a13 a2
ADD a15 a14 a2
SUB a16 a15 a2
ADD a17 a16 a2
SUB a18 a17 a2
ADD a19 a18 a2
SUB a20 a19 a2
ADD a21 a20 a2
SUB a22 a21 a2
ADD a23 a22 a2
SUB a24 a23 a2
ADD a25 a24 a2
SUB a26 a25 a2
ADD a27 a26 a2
SUB a28 a27 a2
ADD a29 a28 a2
SUB a30 a29 a2
ADD a31 a30 a2
SUB a32 a31 a2
PRINT a32

 


结束语

经历了一次,有想吐槽的点(平台太难用,代码真的在上面显示起来好小好丑 小声说)

也有需要我提升的点,字符串在考试之前真的总结过,没想到考试的时候还是有磕绊,对于特定函数(empty)的不熟悉,还有对于循环的跳出条件,没有很灵活地处理

这些都是需要之后提升的点

以及觉得hw真的很注重工程代码的考查

1.代码的规范性(命名规范,函数数据结构,边界值,判断条件等)

2.注释的添加

3.适当地函数有利于解决复杂的问题(代码的精简,思维的转变)

加油啦

  • 19
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值