原题链接
正文开始
在开始做题前我们先复习一下题目中提到的变量
/**
* n 表示总的磁盘数
* s 阵列的条带大小
* l 现存的磁盘数目
* m 待读取的块数
* disklenth 该变量表示一个磁盘包含的块数,题目中并没有提出,在这里提出方便后面的计算
*/
前四个变量调一下顺序看着怎么觉得不对劲啊 滑稽
要做这个题首先要读懂题目意思,这个题目又臭又长,废话多,要在漫长的文字中寻找有用的信息的确是一件考验耐心的事。简单来说,这个题的意思就是给定考生一个块号,然后用程序计算出该块上的内容。
块在磁盘上的存储规则
在了解阵列存储规则之前先定义两个结构体
typedef struct Disk
{
int disknum;//磁盘号
string content;//磁盘上的内容
}Disk;//磁盘结构体
typedef struct
{
int disknum;//块所在的磁盘号,如下图所示第六个块的disknum为0
int posi;//该块在所在磁盘中的位置,如下图所示第六个块的posi为2
}Block;//块结构体
Disk disk[1005];//用于存储存在的磁盘的磁盘号和该磁盘上的内容
int block[1005];//用于存储待查询的块的块号
例: 如下的RAID5阵列由三个磁盘组成,每个条带包含两个块(用虚线隔开的一个长方形表示一个块,连续两个长方形组成的一个正方形表示一个条带)每个磁盘有六个块。
现在开始探索规则,为了方便描述,做一下规定,以每个磁盘为一列,磁盘上条带号相同的条带为一行。如上图阵列可分为三行三列。
1、要先计算出所求块所在的行号,可由下式得到:
bandnum=blknum/(s*(n-1));//blknum为块号
如上图块号为6的行号为1。
2、每一行上校验条带所在的磁盘号可由下式算出:
db=n-1-bandnum%n;//db为一行中该行校验条带所在的磁盘号
如上图第一行的校验条带所在的磁盘号为1。
3、一行中的起始存储块所在的磁盘号为:db+1,则由此得一个块所在磁盘的磁盘号为:
diskn=(db+1+blknum%(s*(n-1))/s)%n;//diskn为一个块所在磁盘的磁盘号
4、一个块在所在磁盘中的位置为:
pos=bandnum*s+blknum%s;//pos为一个块在所在磁盘中的位置
经过以上步骤我们已经得到了一个块在阵列中的确切位置,接下来就到了输出该块的内容了。
一个磁盘的容量为:
disklenth=disk[0].content.size()/8
一个阵列的最大容量为:
max=disklenth*(n-1)
1、若块号大于等于max,块超出阵列总长度,输出“-”;
2、若块号不超过max,在disk[ ]中查找该块所在的磁盘号是否存在disk[ ]中,若存在直接读出输出即可;
3、若该块所在的磁盘号不在在disk[ ]中,则说明该磁盘遗失,需要其他磁盘异或得到结果。但若n-1>l,则由于磁盘数太少不能异或得到结果输出"-"。若n-1=l则可由其它磁盘异或得到结果。
(第三步涉及字符串转整型,大体思路就是先把字符串转为数字,然后数字进行异或,输出异或后的结果)
代码
#include <iostream>
#include <string>
using namespace std;
typedef struct Disk
{
int disknum;
string content;
}Disk;
typedef struct
{
int disknum;
int posi;
}Block;
int n,s,l,m,disklenth;
Disk disk[1005];//用于存储存在的磁盘的磁盘号和该磁盘上的内容
int block[1005];//用于存储待查询的块的块号
Block getPosition(int blknum);//获取块在磁盘上的位置
int sixteenPower(int power);//计算16的power次幂
int hextoDec(char c);//将16进制字符c转化成十进制数字
int stringtoInt(string str);//将16进制字符串str转化成十进制整型数字
void print(int blknum);//打印块号为blknum的块的内容
int main()
{
std::ios::sync_with_stdio(false);
cin>>n>>s>>l;
for(int i=0;i<l;i++)//存现存的磁盘
{
cin>>disk[i].disknum;
cin>>disk[i].content;
}
disklenth=disk[0].content.size()/8;
cin>>m;
for(int i=0;i<m;i++)
cin>>block[i];
for(int i=0;i<m;i++)
print(block[i]);
return 0;
}
Block getPosition(int blknum)
{
int bandnum,diskn,pos,b;
bandnum=blknum/(s*(n-1));//该块所在的行号
b=blknum%(s*(n-1));
int db=n-1-bandnum%n;//db为一行中该行校验条带所在的磁盘号
int i=0;
diskn=(db+1+blknum%(s*(n-1))/s)%n;//该块所在的磁盘号
pos=bandnum*s+blknum%s;//该块在磁盘上的位置
Block block;
block.disknum=diskn;
block.posi=pos;
return block;
}
int sixteenPower(int power)
{
if(power==0)
return 1;
int res=1;
for(int i=0;i<power;i++)
res*=16;
return res;
}
int hextoDec(char c)
{
int ans;
switch(c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':ans=c-'0';break;
case 'a':
case 'A':ans=10;break;
case 'b':
case 'B':ans=11;break;
case 'c':
case 'C':ans=12;break;
case 'd':
case 'D':ans=13;break;
case 'e':
case 'E':ans=14;break;
case 'f':
case 'F':ans=15;break;
}
return ans;
}
int stringtoInt(string str)
{
int ans=0;
for(int i=str.size()-1,j=0;i>=0;i--,j++)//从低位到高位依次转化
ans+=hextoDec(str[i])*sixteenPower(j);
return ans;
}
void print(int blknum)
{
if(blknum>=disklenth*(n-1))//检验块号是否超过阵列的最大容量
{
cout<<"-"<<endl;
return;
}
Block bl=getPosition(blknum);
for(int j=0;j<l;j++)//检验该块是否存在于已知磁盘上
{
if(disk[j].disknum==bl.disknum)
{
string s=disk[j].content.substr(bl.posi*8,8);
cout<<s<<endl;
return;
}
}
if(n-1>l)//若不能推导出输出"-"
{
cout<<"-"<<endl;
return;
}
int res=0,b=0;
string str;
for(int i=0;i<l;i++)//可以推导出
{
str=disk[i].content.substr(bl.posi*8,8);
if(b==0)
{
b++;
res=stringtoInt(str);
continue;
}
res=res^stringtoInt(str);
}
cout<<hex<<uppercase<<res<<endl;//以16进制大写字母的形式输出
}