#include <iostream>
#include <stdio.h>
#include <stack>
#include <string>
#include <stdlib.h> //用于atoi函数
using namespace std;
/*
问题:给定两个32位的证书N与M,以及表示比特位置的i与j。编写一个方法,将M插入N,使得M从N的第j位开始,到第i位结束(j>i)。
嘉定从j位得到i位足以容纳M,也即若M=10011,那么j和i之间至少可以容纳5个位。例如,不可能出现j=3和i=2的情况,因为第
3位和第2位之间放不下M。
示例输入:N= 100 0000 0000
M= 100 11
i= 2,j =6
输出:N= 100 0100 1100
分析:这个问题实际上就是寻找这样一个整数x,x与y进行位操作后,以y全部出现。
等同于以下步骤:
1:先将N从第j位到第i位之间变成0,设置数M,问题转化为如何使得某一位变成0,从而将从第j位到第i位依次都变成0
2:将M整体向左移动i位得到新的M
3: 将N和新的M进行或运算
输入:
10000000000 (N) 10011(M) 2(i) 6(j)
输出:
10001001100
关键:
1
书上解法:
对一个数从第j位到第i位进行清零,涉及到两次掩码运算。
首先:将0取反,得到全1的数,将该全1的数向左移动j+`位,因为这里最低位是从0开始计算的,0到第j位全为0,实际上是j+1个位都为0,因此
向左移动j+1位,记得到P
然后:需要将第i位以下的位全部变成1,可以用1向左移动i位,然后减去1,记得到Q
最后: P|Q 得到最终掩码R,将R和N进行与运算
想不到:将0取反右移j+1位即可使得第j位前面均为1
2 注意输入的N和M都是字符串,需要转化为二进制
*/
/*
对一个数从第j位到第i位进行清零,涉及到两次掩码运算。
首先:将0取反,得到全1的数,将该全1的数向左移动j+`位,因为这里最低位是从0开始计算的,0到第j位全为0,实际上是j+1个位都为0,因此
向左移动j+1位,记得到P
然后:需要将第i位以下的位全部变成1,可以用1向左移动i位,然后减去1,记得到Q
最后: P|Q 得到最终掩码R,将R和N进行与运算
*/
int clearBit(int N , int i , int j)
{
if(i > j)
{
return -1;
}
int allOnes = ~0;
int P = allOnes << (j+1);
int Q = (1 << i) - 1;
int R = P | Q;
int result = R & N;
return result;
}
/*
1:先将N从第j位到第i位之间变成0
2:将M整体向左移动i位得到新的M
3: 将N和新的M进行或运算
*/
int replaceBit(int N , int M , int i , int j)
{
if(i < 0 || j < 0 || i > j)
{
return -1;
}
int C = clearBit(N , i , j);
M = M << i;
int result = C | M;
return result;
}
stack<int> tenToTwo(int num)
{
stack<int> stackResult;
do{
int j = num % 2;
stackResult.push(j);
num /= 2;
}while(num);
return stackResult;
}
void print(stack<int> stackResult)
{
while(!stackResult.empty())
{
int value = stackResult.top();
stackResult.pop();
cout << value;
}
cout << endl;
}
//将字符串中表示的二进制整数转化为10进制整数,只能每次取一位,并乘以2^i,进行累加
int toInt(string& str)
{
if(str.empty())
{
return -1;
}
//字符串应该从后向前获取
int size =str.size() ;
int num;
int count = 0;
int result = 0;
for(int i = size -1 ; i >= 0 ; i--)
{
num = str[i] - '0';
int value = (int) pow(2 , count);
result += num * value;
count++;
}
return result;
//int value = atoi(str.c_str());//这里输入的是二进制整数需要转换,不能直接用字符串转换
//return value;
}
void process()
{
string strN , strM ;
int N , M;
int i ,j;
while(cin >> strN >> strM >> i >> j)
{
N = toInt(strN);
M = toInt(strM);
int result = replaceBit(N , M , i , j);
//得到结果后,需要转化成二进制数,十进制转二进制就是除二取余,然后逆序输出即可
stack<int> stackResult = tenToTwo(result);
print(stackResult);
}
}
int main(int argc, char* argv[])
{
process();
getchar();
return 0;
}